Akshay J
Akshay J

Reputation: 5458

Stop AsyncTask when fragment is replaced

In my fragment I have 2 AsyncTasks continuously running. The requirement is that when the user switches to a different frame using the Drawer menu, these tasks should be cancelled. However when the user presses the home button, these tasks should keep running.

I used the following code in that fragment:

@Override
public void onStop() {
    super.onStop();

    if(asyncTripWaiter != null && asyncTripWaiter.getStatus() == AsyncTask.Status.RUNNING)
        asyncTripWaiter.cancel(true);

    if(asyncTripTracker != null && asyncTripTracker.getStatus() == AsyncTask.Status.RUNNING)
        asyncTripTracker.cancel(true);
} 

The problem is that this piece of code executes even when the home button is pressed. How can I make it effective only when the fragment is switched.

Upvotes: 1

Views: 1391

Answers (3)

J.D.1731
J.D.1731

Reputation: 415

It's not so simple, please consider the situation when your fragment is going to back stack, then you can reach methods onPause() and onStop(). User can either come back to this fragment in a second when AsyncTask is still running. Then it could be not really efficient to call AsyncTask once again.

There is actually two options, first one is the Syncing architecture solution when you're syncing your model separately from visible fragments, then you don't have to cancel AsyncTask but it requires to change your application logic. You can hear about it on Android Application Architecture (Android Dev Summit 2015) As the lecturer said, it's not so important what kind of architecture you have, but it matters how you handle your data loading and caching.

So the first option is to cache the data separately from fragments and activities.

Second option is to keep your AsyncTask alive but check is fragment the active one and/or cache the data even if it's not. User can go back to this fragment later.

This will not happen when fragment is destroyed so you can listen on onDestroy method and set the flag like destroyed = true;. When AsyncTask returns you can check

if (!destroyed) { 
    // do your job
}

Upvotes: 1

Farhan
Farhan

Reputation: 13390

Since you only need to cancel when you are switching, so 1 way of doing this would be to expose some public functions of the fragment.

Switching of fragments most probably be happening in activity, so before replacing, call that exposed function of fragment to cancel the asynctask.

e.g

In your fragment:

public void cancelAllTasks(){
    // your logic to cancel tasks
}

In Activity:

yourFragment.cancelAllTasks();
...
replaceAnotherFragmentCode();

Upvotes: 0

Brijesh Kumar
Brijesh Kumar

Reputation: 1685

You can try it like this

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (!isVisibleToUser) {
        if(asyncTripWaiter != null && asyncTripWaiter.getStatus() == AsyncTask.Status.RUNNING)
            asyncTripWaiter.cancel(true);

        if(asyncTripTracker != null && asyncTripTracker.getStatus() == AsyncTask.Status.RUNNING)
            asyncTripTracker.cancel(true);
    }
}

setUserVisibleHint() is a override method of fragment class.

Upvotes: 0

Related Questions