Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to gracefully handle exception inside AsyncTask in Android?

I have an AsyncTask to do SQLite database migration in the background (create or upgrade). Let's say somehow an IOException or SQLiteException is thrown inside doInBackground and it's pointless for the app to continue running because database state might be not in desired state. I'm kind of confused on what to do in this situation.

I'm thinking about letting the application crash as soon as possible and show dialog with error message, but I'm not really sure how to this inside doInBackground, because:

  1. This function is not executed in UI thread so I don't know if I can show a dialog.
  2. I don't know how to access current activity within AsyncTask, so I can't finish() it.
  3. I want to somehow throw the exception to the upper layer and let an activity handle it, but it's not possible because doInBackground doesn't list IOException as a checked exception.

Anyone has an advice on how to gracefully handle this situation?

like image 943
Andree Avatar asked Jan 08 '13 09:01

Andree


People also ask

What is the problem with AsyncTask in Android?

In summary, the three most common issues with AsyncTask are: Memory leaks. Cancellation of background work. Computational cost.

Is AsyncTask deprecated in Android?

AsyncTask is used to perform time talking operations in android, but it's marked as deprecated from android 11.

What method must be overridden for using AsyncTask?

AsyncTask must be subclassed to be used. The subclass will override at least one method ( doInBackground(Params...) ), and most often will override a second one ( onPostExecute(Result) .)


1 Answers

You can't show dialog in non-ui thread. You can pass activity reference to async task. To handle this situation you can try catch the exception in doInBackground and re-throw it in onPostExecute

e.g.

private class MyAsyncTaskTask extends AsyncTask<...> {

     private Activity ownerActivity;
     private Exception exceptionToBeThrown;

     public MyAsyncTaskTask(Activity activity) {
         // keep activity reference
         this.ownerActivity = activity;
     }

     protected Long doInBackground(...) {
         try {
             ...
         } catch (Exception e) {
             // save exception and re-thrown it then. 
             exceptionToBeThrown = e;
         }
     }

     protected void onPostExecute(...) {
         // Check if exception exists.
         if (exceptionToBeThrown != null) {
             ownerActivity.handleXXX();
             throw exceptionToBeThrown;
         }
     }
 }

If you async task is in Acvitiy class, then you can directly access it, e.g.,

public class MyActivity extends Activity {
    ...
    AsyncTask<...> task = new AsyncTask<...>() {
        public void onPostExecute(...) {
            // Access activity directly
            MyActivity.this.xxx()
        }
    }
}
like image 98
Qiang Jin Avatar answered Oct 02 '22 23:10

Qiang Jin