11

バックグラウンドでSQLiteデータベースの移行(作成またはアップグレード)を行うためのAsyncTaskがあります。どういうわけか、IOExceptionまたはSQLiteExceptionがdoInBackground内でスローれ、データベースの状態が目的の状態にない可能性があるため、アプリが実行を継続することは無意味であるとしましょう。私はこの状況で何をすべきかについて少し混乱しています。

アプリケーションをできるだけ早くクラッシュさせ、エラーメッセージ付きのダイアログを表示することを考えていますが、doInBackground内でこれを行う方法がよくわかりません。理由は、次のとおりです。

  1. この関数はUIスレッドでは実行されないため、ダイアログを表示できるかどうかわかりません。
  2. AsyncTask内の現在のアクティビティにアクセスする方法がわからないため、 finish()できません。
  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 に答える