11

我有一个AsyncTask在后台进行 SQLite 数据库迁移(创建或升级)。假设以某种方式在 doInBackground 中抛出了IOException 或 SQLiteException并且应用程序继续运行毫无意义,因为数据库状态可能未处于所需状态。我有点困惑在这种情况下该怎么做。

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

  1. 此函数不在 UI 线程中执行,所以我不知道是否可以显示对话框。
  2. 我不知道如何访问AsyncTask中的当前活动,所以我无法完成()它。
  3. 我想以某种方式将异常抛出到上层并让活动处理它,但这是不可能的,因为doInBackground没有将IOException列为检查异常。

有人对如何优雅地处理这种情况有建议吗?

4

3 回答 3

19

您不能在非 ui 线程中显示对话框。您可以将活动引用传递给异步任务。要处理这种情况,您可以尝试在 doInBackground 中捕获异常并在 onPostExecute 中重新抛出它

例如

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()
        }
    }
}
于 2013-01-08T09:36:57.213 回答
0

每次在 doInBackground 中发生此类异常时,将一个唯一字符串返回给 onPostExecute。并在 onPostExecute 显示一个 AlertDialog 显示适当的消息并要求重试或其他什么。

于 2013-01-08T09:36:55.757 回答
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);

}
于 2017-04-01T02:47:49.467 回答