如何在Android中的AsyncTask中优雅地处理异常?

时间:2013-01-08 09:23:31

标签: android exception-handling

我有 AsyncTask 在后台进行SQLite数据库迁移(创建或升级)。假设 IOException SQLiteException doInBackground 中被抛出,应用程序继续运行是没有意义的,因为数据库状态可能不是所需的状态。我对在这种情况下该怎么做感到困惑。

我正在考虑让应用程序尽快崩溃并显示带有错误消息的对话框,但我不确定如何在 doInBackground 中进行此操作,因为:

  1. 此功能未在UI线程中执行,因此我不知道是否可以显示对话框。
  2. 我不知道如何访问 AsyncTask 中的当前活动,所以我不能完成()它。
  3. 我想以某种方式将异常抛出到上层并让一个活动处理它,但这是不可能的,因为 doInBackground 不会将 IOException 列为已检查的异常
  4. 任何人都有关于如何优雅地处理这种情况的建议吗?

3 个答案:

答案 0 :(得分:19)

您无法在非ui线程中显示对话框。您可以将活动引用传递给异步任务。要处理这种情况,您可以尝试捕获doInBackground中的异常并将其重新抛入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;
         }
     }
 }

如果您的异步任务在Acvitiy类中,那么您可以直接访问它,例如,

public class MyActivity extends Activity {
    ...
    AsyncTask<...> task = new AsyncTask<...>() {
        public void onPostExecute(...) {
            // Access activity directly
            MyActivity.this.xxx()
        }
    }
}

答案 1 :(得分:0)

每次在doInBackground中发生onPostExecute这样的异常时,

返回一个唯一的字符串。并在onPostExecute中显示一个AlertDialog,显示相应的消息并要求再次尝试。

答案 2 :(得分:0)

我处理它的方法。

/**
 * Created by Daniel on 02/04/2016.
 */
public abstract class AsyncTaskEnhanced<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {

    // Avoids cyclic calls.
    private boolean onPostExecuteCalled = false;
    private Exception exception;

    @Override
    protected final Result doInBackground(Params... params) {

        try {

            return this.doInBackgroundWithFaultTolerance(params);
        } catch (Exception exception) {

            this.exception = nre;
        }

        return null;
    }

    @Override
    protected final void onPostExecute(Result result) {

        if (this.onPostExecuteCalled) return;

        this.onPostExecuteCalled = true;

        super.onPostExecute(result);

        this.onPostExecuteWithFaultTolerance(result, this.exception);
    }

    protected abstract Result doInBackgroundWithFaultTolerance(Params... params) throws Exception;

    protected abstract void onPostExecuteWithFaultTolerance(Result result, Exception ex);

}