Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Back button press while AsyncTask is running

I have an ActivityA, which has a Button. Upon Click on the button, it opens up another ActivityB.

onCreate() method of ActivityB, I am starting AsyncTask which connect to server and fetch the results and display it to the screen.

Here is the Code of Activity B:

public class ActivityB extends Activity {
    AsyncFetch asyncFetch;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(null != savedInstanceState) {
            return;
        }
        asyncFetch = new AsyncFetch();
        asyncFetch.execute();
    }
}


private class AsyncFetch extends AsyncTask<Object, Void, Object> {
    @Override
    protected void onPostExecute(Object o) {

    }

    @Override
    protected Object doInBackground(Object... params) {
        //contacts the http server.
    }
}

While executing AsyncFetch, when I hit back press, the ActivityB is not getting destroyed immediately. But gets destroyed after AsyncTask gets completed.

How do I implement this to avoid back press freeze? I tried below:

@Override
protected void onDestroy() {
    asyncFetch.cancel(true);
    super.onDestroy();
}

But still it waits the AsyncTask to cancel or complete.

Like GMail app, when I open something. While in the process if I press back button, it just comes out of that Activity.

Is there any other way of implementing background process? Any design pattern to implement this? Please let me know.

Any help is appreciated.

like image 296
User12111111 Avatar asked Oct 17 '14 08:10

User12111111


4 Answers

Just handle yourself the onBackPressed() method:

@Override
public void onBackPressed()
{
    if (asyncFetch != null)
        asyncFetch.cancel(true);

    super.onBackPressed();
}
like image 112
Alex Avatar answered Sep 21 '22 11:09

Alex


From the android developer's website:

Cancelling a task

A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)

So in short, you can mark the AsyncTask as cancelled in onPause() or onBackPressed() from your Activity, and then you can add a few if blocks in doInBackground() and return right away if task is cancelled.

For example:

@Override
protected void doInBackground(Object... params){

    // do some work

    if(isCancelled()){
        // end task right away
        return null;
    }
    // if task is not cancelled yet,
    // do some other work
}

However, if the network operation has already started, you will need to cancel it from your HttpClient.

like image 24
Endor Avatar answered Sep 18 '22 11:09

Endor


Try this:

@Override
public void onBackPressed() {
    asyncFetch.cancel(true);
    // If you want to finish the activity you can use below code
    // finish(); 
}
like image 24
Batuhan Coşkun Avatar answered Sep 20 '22 11:09

Batuhan Coşkun


Here we go. Try this.

@Override
public void onBackPressed() {
    if (asyncFetch.getStatus() == AsyncTask.Status.RUNNING) {
       asyncFetch.cancel(true);
    } 
    finish(); 
}
like image 28
Remees M Syde Avatar answered Sep 20 '22 11:09

Remees M Syde