The callback methods defined by AsyncTask
dictate that we cannot throw checked exceptions, so we must wrap any code that throws checked exceptions with try
/catch
blocks. Unchecked exceptions that propagate out of AsyncTask's methods will crash our application, so we must test carefully and handle these if necessary.
For the callback methods that run on the main thread—onPreExecute
, onProgressUpdate
, onPostExecute
, and onCancelled
—we can catch exceptions in the method and directly update the user interface to alert the user.
Of course, exceptions are likely to arise in our doInBackground
method too, as this is where the bulk of the work of AsyncTask
is done, but unfortunately, we can't update the user interface from doInBackground
. A simple solution is to have doInBackground
return an object that may contain either the result or an exception, as follows:
static class Result<T> { private T actual; private Exception exc; } @Override protected final Result<T> doInBackground(Void... params) { Result<T> result = new Result<T>(); try { result.actual = calculateResult(); } catch (Exception exc) { result.exc = exc; } return result; } protected abstract T calculateResult() throws Exception;
Now we can check in onPostExecute
for the presence of an Exception
in the Result
object. If there is one, we can deal with it, perhaps by alerting the user; otherwise, we just use the actual result as normal.
@Override protected final void onPostExecute(Result<R> result) { if (result.exc != null) { // … alert the user … } else { // … success, continue as normal … } }
In the downloadable code, you'll find a handy SafeAsyncTask
class that takes care of exception handling, and makes it easy to deal with exceptions or results.
3.16.48.122