javaandroidandroid-asynctaskandroid-thread

How to cancle AsyncTask in Android


In my application i have 2 AsyncTask methods and i want when activity go to onPause cancel this AsyncTasks and in onResume start from the beginning.
I write below codes, i pressed home button and application go to onPause and open again this app from recent apps
My mean is call onPause and onResume !

But when application run again (from recent app), call onResume but not start AsyncTask from the beginning!

My codes :

@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;
    }
}

How can i fix it and in onResume start from beginning this AsyncTasks ?


Solution

  • When you cancel asynctask, although it is canceled. Your asyncTask will keep running until doInBackGround() finishes its work.

    So for your GetOriginalVideosAsync do this in 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;
    }
    

    And for your GetCompressedVideosAsync do this in 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;
    }
    

    update

    Try this in both tasks at the same place that I told you to:

    if(isCancelled){
    break;
    }
    

    update 2

    Look your asyncTaks must be member variables of the activity

    class MyActivity extends ........{
    
    private GetOriginalVideosAsync orginalTask;
    private GetCompressedVideosAsync compressedTask;
    .......
    
    
    
    }
    

    Call on pause like this:

    @Override
    protected void onPause() {
    
        orginalTask.cancel(true);
        compressedTask.cancel(true);
        super.onPause();
    
    }
    

    and

    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()]));
        }
    }