官术网_书友最值得收藏!

Handling exceptions

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. First we are going to create a generic class for storing the result of an operation and a member to store an exception:

public class Result<T> {
    public T result;
    public Throwable error;
}

In the next step we will create a new download AsyncTask, called SafeDownloadImageTask, that takes care of the exception handling and has a result of type Result<Bitmap> instead of the Bitmap:

public class SafeDownloadImageTask extends
  AsyncTask<URL, Integer, Result<Bitmap>> {

   // Method executed on the Background Thread
   protected Result<Bitmap> doInBackground(URL... params) {
     Result<Bitmap> result = new Result<Bitmap>();
     try {
           // elided for brevity ...
          ...
       result.result = bitmap;
     } catch (Throwable e) {
       result.error = e;
     } ...     
   }
   return result;
}

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 and use the bitmap from the result:

@Override
protected final void onPostExecute(Result<Bitmap> result) {
  ...
  if ( result.error!= null) {
    // ... alert the user ...
    ...
    Log.e("SafeDownloadImageTask",
          "Failed to download image ",result.exception);
    loadDefaultImage(imageView);
  } else {
    // ... success, continue as normal ...
    imageView.setImageBitmap(result.actual);
  }
}

With a safe implementation like the one above, any error thrown on the background thread is safely forwarded to the main thread and does not affect the normal lifecycle of the AsyncTask. Let's try to retrieve an image that does not exist and see if the exception is handled properly:

URL url = new URL("http://img.allw.mn" +
                  "/content/www/2009/03/notfound.jpg");
new SafeDownloadImageTask(ShowMyPuppyActivity.this, iv)
.execute(url);

As expected, the error was caught, wrapped in a Result object, and printed in the Android log with a stack trace pointing to the SafeDownloadImageTask.doInBrackground method:

...downloadBitmap(SafeDownloadImageTask.java:85)
...doInBackground(SafeDownloadImageTask.java:60)
...

84: if (responseCode != HttpURLConnection.HTTP_OK){
85:      throw new Exception(...);
86: }
主站蜘蛛池模板: 马公市| 黑河市| 梧州市| 定日县| 绥江县| 鄂托克前旗| 汉源县| 噶尔县| 新丰县| 高唐县| 宁河县| 咸阳市| 田阳县| 巩留县| 深圳市| 霸州市| 枣阳市| 河东区| 新丰县| 刚察县| 玉林市| 苏尼特左旗| 南充市| 大同市| 淮北市| 民勤县| 延吉市| 甘德县| 老河口市| 靖州| 柘城县| 炉霍县| 黑山县| 双城市| 邵阳县| 革吉县| 萨嘎县| 嘉黎县| 黄平县| 桂林市| 额敏县|