【问题标题】:How to cancle AsyncTask in Android如何在 Android 中取消 AsyncTask
【发布时间】:2020-04-21 10:18:19
【问题描述】:

在我的应用程序中,我有 2 个 AsyncTask 方法,我想在 activity 转到 onPause 时取消此 AsyncTasks 和 onResume 从头开始
我写了下面的代码,我按下主页按钮和应用程序转到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 从头开始 这个AsyncTasks ?

【问题讨论】:

    标签: java android android-asynctask android-thread


    【解决方案1】:

    当你取消 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,请在 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()]));
        }
    }
    

    【讨论】:

    • 感谢我的朋友,但在 onResume 中再次继续之前的任务!不要重新开始!
    • 你怎么知道它没有被取消??
    • 您有空闲时间连接到我的电脑以显示我的代码吗?
    • 检查更新 2 并保留我在更新 1 中告诉你的内容。
    【解决方案2】:

    可以通过调用 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

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

    问题

        ...
        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全局变量vs局部变量”有更多的理解,希望解释有所帮助,加油。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多