1

データをフェッチする AsyncTasks がたくさんあります。ダイアログ ボックスを表示して、実行中に進行状況を更新します。これにより、アプリがバックグラウンド (非表示) にあるときにアプリがクラッシュすることがあります。私のコードは以下で呼び出されました。ダイアログ ボックスを完全にリファクタリングせずにアプリがクラッシュしないようにするには、どのようなチェックを行うことができますか?

これらは DownloadAsyncTask で宣言され、コンストラクターに渡されます

protected ProgressDialog mDialog;
protected String mDialogMessage = "Loading Data";
protected ProgressBar progBar;

doInBackground() {
    if ( mProgressBar != null && mProgressBar.getVisibility() == View.INVISIBLE) {
        mUIThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                mProgressBar.setVisibility(View.VISIBLE);
            }
        });
    } else if ( mDialog != null && !mDialog.isShowing() ) {
        mUIThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                mDialog.setMessage(mDialogMessage);
                mDialog.show();
            }
        });
    }
}

そしてonPostExecute()

@Override
protected void onPostExecute(DefaultHandler handler) {
    super.onPostExecute(handler);
    if ( progBar != null && progBar.getVisibility() == View.VISIBLE ) {
        progBar.setVisibility(View.INVISIBLE);
    } else if ( mDialog != null && mDialog.isShowing() ) {
        try {
            mDialog.dismiss();
        } catch (Exception e) {
        }   
    }   
}

更新されたクラッシュ ログ:

12-20 15:19:15.802: E/AndroidRuntime(9529):
android.view.WindowManager$BadTokenException: ウィンドウを追加できません -- トークン android.os.BinderProxy@41a37908 が無効です。あなたの活動は進んでいますか?12-20 15:19:15.802: E/AndroidRuntime(9529): android.view.ViewRootImpl.setView(ViewRootImpl.java:567) で 12-20 15:19:15.802: E/AndroidRuntime(9529): Android で。 view.WindowManagerGlobal.addView(WindowManagerGlobal.java:246) 12-20 15:19:15.802: E/AndroidRuntime(9529): Android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 12-20 15:19: 15.802: E/AndroidRuntime(9529): android.app.Dialog.show(Dialog.java:281) 12-20 15:19:15.802: E/AndroidRuntime(9529): com.*.DownloadAsyncTask$2.run( DownloadAsyncTask.java:119) 12-20 15:19:15.802: E/AndroidRuntime(9529): android.os.Handler.handleCallback(Handler.java:725) 12-20 15:19:15.802:

4

3 に答える 3

1

バックグラウンド スレッドから UI に触れています。Android は技術的には「更新しない」と言いますが、「バックグラウンド スレッドで UI を操作しない」と読むのが最善です。あなたのif声明は本質的に「UIについて(...)がtrueの場合、このタスクを投稿して将来のある時点でUIスレッドで実行する」と述べています。UI スレッドで実行するまでRunnableに、UI の状態が変更されている可能性があります。ロジック全体をカプセル化し、それを UI スレッドに送信して実行する方がよいでしょう。持っている 2 つの を組み合わせて 1 つの で出荷することでそれを行うことができますRunnableが、ハンドラーを直接扱う必要がないように設計されています。doInBackGround を呼び出すと、UI スレッドの呼び出しがpostAsyncTaskpublishProgress()onProgressUpdate()メンバー。Runnableしたがって、コードをsに結合してメソッドに移動する方が簡単ですonProgressUpdate()

何かのようなもの -

   void onProgressUpdate() {
            if (mProgressBar != null && mProgressBar.getVisibility() == View.INVISIBLE) {
                mProgressBar.setVisibility(View.VISIBLE);
            } else if (mDialog != null && !mDialog.isShowing()) {
                mDialog.setMessage(mDialogMessage);
                mDialog.show();
            }
        }
于 2012-12-22T02:47:24.027 に答える
0

クラッシュを回避するには、runOnUiThread(runnable) を使用します。これにより、基本的に UI スレッドの run メソッドでコード セグメントが実行されます。以下に示すように、run メソッドで実行するすべての UI 操作をラップします。

したがって、コードは次のようになります。

yourActivity.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                // whatever UI operations..
                ..
                mDialog.setMessage(mDialogMessage);
                mDialog.show();
            }

});

于 2012-12-22T05:29:51.967 に答える