2

In my application I have an AsyncTask and I've also created a list, to add task to that list. In the AsyncTask I am downloading some information, and it works just fine, but, when close activity using finish(), I often get Force Close because the AsyncTask wasn't closed and when it reaches to onPostExecute and wants to interact with UI, it crashes caused activity has been destroyed!

this is what I've tried but didn't work:

  for (int i = 0; i<tasks.size(); i++){
           tasks.get(i).cancel(true);
       }
  finish();

so is there way force stop AsyncTasks ?

Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38

5 Answers5

4

You are intereset in asyncTask.cancel(true), actually passing true in its parameter, as in docs stay:

mayInterruptIfRunning true if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete.

then inside your AsyncTask.doInBackground you can have try/catch as below - but that requires you to have blocking calls that throw InterruptedException, otherwise you need to check isCancelled() from time to time:

@Override
protected Void doInBackground(Void... params) {
  try {
    /// do work, 
  } catch (InterruptedException e) {
    if ( isCancelled() ) {
      // cancel(true) called, dont touch UI!
    }
  }
  return null;
}

also, its safe to check for isCancelled() at the start of onPostExecute().

when it reaches to onPostExecute and wants to interact with UI, it crashes

thats other problem, if you interact inside AsyncTask with GUI, I suggest first: to make your AsyncTask a static class, pass reference to your Activity or Fragment to AsyncTask constructor and then store it as a WeakReference<MyActivity> actRef. Then when you need it use if ( actRef.get() != null ) { // use it. }. This way you want leak references to your activity/fragment or use dead UI object.

marcinj
  • 48,511
  • 9
  • 79
  • 100
2

Try create own boolean variable.

boolean stopNow = false;
asyncTask.start();

... inside async:

while( ...)
 {
   if( stopNow == true)  finish(); // return();
   ... your main async code
 }

.... outside async (at moment when you need force stop async, in your case in Activity.onDestroy() or Activity.onPause()):

stopNow = true; 
Tapa Save
  • 4,769
  • 5
  • 32
  • 54
1

You need to tell your AsyncTask that it shall cancel its work. Therefore you need to regularly check for self.isCanceled() in your AsyncTask implementation. If it's result is true your implementation needs to stop its work otherwise it will complete the whole job or run forever, depending on the implementation.

Lars Blumberg
  • 19,326
  • 11
  • 90
  • 127
1

You should check if activity isDestroyed() in your AsyncTask's onPostExecute. Also, if you're using internal AsyncTask class then make it static. Use WeakReference for referencing yout Activity to prevent memory leaks. (There is no way to force stop AsyncTask).

konmik
  • 3,150
  • 19
  • 15
  • what about `onCancelled()` method [stated in official doc in Cancelling a task section](http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean)) – Kaushik Oct 06 '14 at 12:58
  • This method does not interrupt your task. It is being called AFTER your task finish itself. – konmik Oct 07 '14 at 07:37
1

Here is the example how to achieve this...

public class MyTask extends AsyncTask<Void, Void, Void> {

private volatile boolean running = true;
private final ProgressDialog progressDialog;

public MyTask(Context ctx) {
    progressDialog = gimmeOne(ctx);

    progressDialog.setCancelable(true);
    progressDialog.setOnCancelListener(new OnCancelListener() {
        @Override
        public void onCancel(DialogInterface dialog) {
            // actually could set running = false; right here, but I'll
            // stick to contract.
            cancel(true);
        }
    });

}

@Override
protected void onPreExecute() {
    progressDialog.show();
}

@Override
protected void onCancelled() {
    running = false;
}

@Override
protected Void doInBackground(Void... params) {

    while (running) {
        // does the hard work
    }
    return null;
}

// ...

}
Arpit Patel
  • 1,561
  • 13
  • 23