Android、Java、Web系、Linux、マラソン等の備忘録

2013/09/17

AsyncTaskの実行中にProgressDialog表示させ画面回転させるとIllegalArgumentException

0 件のコメント
よくやるやつ。

Activity上でAsyncTaskを継承したクラスのインスタンスを生成。このクラスのコンストラクタでProgressDialogのインスタンスを生成してダイアログを表示。onPostExecuteでダイアログをdismiss()する。このdismissするまでに画面を回転させると、

java.lang.IllegalArgumentException: View not attached to window manager

という例外が発生します。対策の一つとして、そもそも画面を回転させないというのもあり、過去のアプリにもやりましたが、それ以外のとりあえずの対応として、ProgressDialogの処理をActivityにやらせることにしました。

AsyncTaskのインスタンスを生成する前にActivity上にProgressDialogのインスタンスを生成して、AsyncTaskの処理終りにdismiss()。あと、ActivityのonDestroyが走った時に、ダイアログが開いてればdismiss()というやり方でとりあえず手持ちの端末では例外は発生しないようです。

どうやってActivity側からAsyncTaskの処理終りを捕まえるかについてなど処理のイメージは以下のソースで。※手持ちのソースから抜粋したので、コンパイラは通してません。

public class HogeActivity extends Activity {

    private ProgressDialog mDialog = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hoge);

        mDialog = new ProgressDialog(this,
                R.string.msg_loading);
        mDialog.show();

        LoaderTask task = new LoaderTask(){

            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result)
                // 処理終りでダイアログを閉じる
                closeDialog();
            }
        };
        task.execute();
    }

    private static class LoaderTask 
        extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            // なんか処理
            return null;
        }
    }

    private void closeDialog() {
        if(null != mDialog) {
            mDialog.dismiss();
            mDialog = null;
        }
    }

    @Override
    protected void onDestroy() {
        this.closeDialog();
    }
}


参考
mokkouyouの開発日記 ProgressDialogとAsyncTaskの(おそらく)正しい使い方
Android/View_not_attached_to_window_manager - tech.cm55.com

PR
AndroidエンジニアのためのモダンJava

0 件のコメント :

コメントを投稿