繁体   English   中英

如何取消 Android 中的 AsyncTask

[英]How to cancle AsyncTask in Android

在我的应用程序中,我有 2 个AsyncTask方法,我希望在activity go 到onPause时取消此AsyncTask并在onResume从头开始
我写了下面的代码,我按下主页按钮和应用程序 go 到onPause并从最近的应用程序再次打开这个应用程序
我的意思是调用onPauseonResume

但是当应用程序再次运行时(从最近的应用程序),调用onResume但不是从头开始启动AsyncTask

我的代码:

@Override
protected void onResume() {
    super.onResume();
    new Handler(getMainLooper()).postDelayed(() -> {
        //Get compress or upload
        if (bundle == null) {
            //Get video from file
            getLoadOriginalVideos();
            testIsSendPlans = testId;
        }
    }, 500);
}

@Override
protected void onPause() {
    super.onPause();
    new GetOriginalVideosAsync().cancel(true);
    new GetCompressedVideosAsync().cancel(true);
}

private void getLoadOriginalVideos() {
    if (videoList.isEmpty()) {
        File directory = new File(Environment.getExternalStorageDirectory() + File.separator + APPDIR);
        ArrayList<File> filesList = new ArrayList<File>();
        if (directory.isDirectory() && directory.exists()) {
            filesList.addAll(Arrays.asList(getOriginalVideos(directory.listFiles())));
        }
        new GetOriginalVideosAsync().execute(filesList.toArray(new File[filesList.size()]));
    }
}

@SuppressLint("StaticFieldLeak")
class GetOriginalVideosAsync extends AsyncTask<File[], Integer, ArrayList<Video>> {
    File[] files;
    ContentResolver resolver;

    GetOriginalVideosAsync() {
        resolver = context.getContentResolver();
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(ArrayList<Video> videos) {
        Collections.sort(videos, Collections.reverseOrder());
        getLastOriginalVideo(addVideos(videos));
    }

    private ArrayList<Video> addVideos(ArrayList<Video> videos) {
        return new ArrayList<>(videos);
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

    }

    @Override
    protected ArrayList<Video> doInBackground(File[]... arg) {
        files = arg[0];
        for (File file : files) {
            if (!file.isDirectory() && isVideoFile(file.getPath())) {
                videoList.add(new Video(file.getName(), file, new Date(file.lastModified())));
            }
        }
        return videoList;
    }
}

@SuppressLint("StaticFieldLeak")
class GetCompressedVideosAsync extends AsyncTask<File[], Integer, ArrayList<Video>> {
    File[] files;
    ContentResolver resolver;

    GetCompressedVideosAsync() {
        resolver = context.getContentResolver();
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(ArrayList<Video> videos) {
        Collections.sort(videos, Collections.reverseOrder());
        getLastCompressedVideo(addVideos(videos));
    }

    private ArrayList<Video> addVideos(ArrayList<Video> videos) {
        return new ArrayList<>(videos);
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

    }

    @Override
    protected ArrayList<Video> doInBackground(File[]... arg) {
        files = arg[0];
        for (File file : files) {
            if (!file.isDirectory() && isVideoFile(file.getPath())) {
                videoListCompressed.add(new Video(file.getName(), file, new Date(file.lastModified())));
            }
        }
        return videoListCompressed;
    }
}

我该如何修复它并在onResume这个AsyncTask开始?

当你取消 asynctask 时,虽然它被取消了。 您的 asyncTask 将继续运行,直到 doInBackGround() 完成其工作。

因此,对于您的GetOriginalVideosAsync ,请在doInBackground中执行此操作:

@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {

//add this

if(isCancelled){

return null;

}

if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoList.add(new Video(file.getName(), file, new Date(file.lastModified())));
}

}
return videoList;
}

对于您的 GetCompressedVideosAsync 在GetCompressedVideosAsync执行此doInBackground

@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {

//add this    
if(isCancelled){
return null;
}

if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoListCompressed.add(new Video(file.getName(), file, new Date(file.lastModified())));

}

}
return videoListCompressed;
}

更新

在我告诉你的同一个地方尝试这两个任务:

if(isCancelled){
break;
}

更新 2

看你的 asyncTaks 必须是活动的成员变量

class MyActivity extends ........{

private GetOriginalVideosAsync orginalTask;
private GetCompressedVideosAsync compressedTask;
.......



}

像这样调用暂停:

@Override
protected void onPause() {

    orginalTask.cancel(true);
    compressedTask.cancel(true);
    super.onPause();

}

private void getLoadOriginalVideos() {
    if (videoList.isEmpty()) {
        File directory = new File(Environment.getExternalStorageDirectory() + File.separator + APPDIR);
        ArrayList<File> filesList = new ArrayList<File>();
        if (directory.isDirectory() && directory.exists()) {
            filesList.addAll(Arrays.asList(getOriginalVideos(directory.listFiles())));
        }
     orginalTask =   new GetOriginalVideosAsync();

    orginalTask.execute(filesList.toArray(new File[filesList.size()]));
    }
}

可以通过调用 cancel(boolean) 随时取消任务。 调用此方法将导致对 isCancelled() 的后续调用返回 true。 调用此方法后,将在 doInBackground(java.lang.Object[]) 返回后调用 onCancelled(java.lang.Object),而不是 onPostExecute(java.lang.Object)。 为了确保尽快取消任务,如果可能(例如在循环内),您应该始终从 doInBackground(java.lang.Object[]) 定期检查 isCancelled() 的返回值。

来源: https://developer.android.com/reference/android/os/AsyncTask

您在代码中遇到的问题是您正在创建一个新实例而不是使用您创建的同一个实例,您可以通过在 class 级别而不是在方法/块中声明它们来使实例全局可访问来做到这一点等级。

问题

    ...
    new GetOriginalVideosAsync().execute(...) 
    new GetCompressedVideosAsync().execute(...)
    ...
    super.onPause();
    new GetOriginalVideosAsync().cancel(true);
    new GetCompressedVideosAsync().cancel(true);
    ...

正确的方式

    ...        
    getOriginalVideosAsync = new GetOriginalVideosAsync(); // Declare this in class level
    getOriginalVideosAsync.execute(...) // replace old execute code with the instance
    getCompressedVideosAsync = new GetCompressedVideosAsync(); // Declare this in class level
    getCompressedVideoAsync.execute(...) // replace old execute code with the instance
    ...
    super.onPause();
    getOriginalVideosAsync().cancel(true);
    getCompressedVideosAsync().cancel(true);
    ...

看看“java全局变量与局部变量”有更多的理解,希望解释有所帮助,干杯。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM