1

Android Support Library (v4) と ActionBarSherlock を使用しています。プログラムで進行状況ダイアログを閉じようとしています。ダイアログ管理に役立つ小さなユーティリティ クラスをコーディングしました。

ダイアログは から表示されますAsyncTask.onPreExecute。正しく表示されます。次に、デバイスを回転させて構成の変更を開始します。これにより、アクティビティが破棄されます (onDestroy 呼び出しAsyncTask.cancel(true))。AsyncTask.onCancelledが呼び出され、ダイアログを閉じようとしているこのメソッドにあります。しかし、何も起こりません。ダイアログを表示して閉じるためのヘルパー関数は次のとおりです。

    public abstract class DialogHelperActivity extends SherlockFragmentActivity {

        protected void showProgressDialog(final String msg, final String tag){      
            FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
            DialogFragment dialogFragment = ProgressDialogFragment.newInstance(msg);

            ft.add(dialogFragment, tag);
            ft.disallowAddToBackStack();
            ft.commitAllowingStateLoss(); //If I try with regular commit(), exceptions are thrown.
        }

        protected void closeDialog(final String tag){
            FragmentManager fm = this.getSupportFragmentManager();
            Fragment dialogFragment = fm.findFragmentByTag(tag);        

            if(dialogFragment != null){
                FragmentTransaction ft = fm.beginTransaction();
                ft.remove(dialogFragment);
                ft.commitAllowingStateLoss();
            } else {
                System.err.println("dialog not found!"); //This line is hit always
            }               
        }


        public static class ProgressDialogFragment extends SherlockDialogFragment {     

            static ProgressDialogFragment newInstance(final String msg) {
                ProgressDialogFragment adf = new ProgressDialogFragment();
                Bundle bundle = new Bundle();

                bundle.putString("alert-message", msg);

                adf.setArguments(bundle);
                return adf;
            }

            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                this.setCancelable(false);
                int style = DialogFragment.STYLE_NORMAL, theme = 0;
                setStyle(style,theme);
            }

            @Override
            public Dialog onCreateDialog(Bundle savedInstanceState) {
                Bundle bundle = this.getArguments();

                String message = bundle.getString("alert-message");


                ProgressDialog dialog = new ProgressDialog(getActivity());
                if(message != null){
                    dialog.setMessage(message);
                }

                dialog.setCancelable(false);
                dialog.setIndeterminate(true);

                return dialog;
            }       
        }

    }

デバイスをローテーションした後、AsyncTask はキャンセルされます。と から電話closeDielogonPostExecuteていonCancelledます。タグ ID が見つからない ( findFragmentByTagnull を返す) ため、ダイアログは閉じられません。私はこれに困惑しています。showProgressDialogこのタグは、私の実装アクティビティでは静的文字列であるため、との呼び出し間でタグが失われたり変更されたりする可能性はありませんcloseDialog

どんなアイデア/ヒント/提案も大歓迎です。

ありがとう。

4

1 に答える 1

8

AsyncTask問題は、アクティビティの でをキャンセルしていることですonDestroy。これは bg スレッドを取り除くのに問題ありませんがAsyncTask.onCancelled、アクティビティが破棄された後に実行されるため、フラグメントを閉じる場所ではありません。その前に、新しいアクティビティが作成され、フラグメント マネージャーが新しいダイアログを復元します (setRetainInstance(false)デフォルトであると思われる で作成された場合でも)。

通話のタイムラインは次のようなものです。

  1. 画面の回転は構成の変更をトリガーします
  2. 古いアクティビティが入りonDestroy、asynctask をキャンセルします。
  3. 古いダイアログが入りonDetachます。
  4. 新しいアクティビティが作成されます。
  5. 新しいダイアログが作成され、新しいアクティビティに関連付けられて表示されます。
  6. 古いタスクonCancelが実行され、 が呼び出されますcloseDialogが、タグが見つかりません。

私のエラーは、文字列タグがアプリケーション コンテキストでフラグメントをグローバルに識別したと想定していましたが、フラグメント マネージャーによって割り当てられた実際のフラグメント ID は、フラグメント タグ/ID とそのアクティビティ ID の組み合わせであることが判明しました。アクティビティが破棄されるとフラグメントは切り離され、この時点以降、同じタグ/ID を持つ新しいフラグメントがフォアグラウンドにある場合でも、別のアクティビティにアタッチされているため、フラグメント マネージャーは古いアクティビティが破棄されると null を返します。 findFragmentByTag を呼び出します。

ただし、新しいフラグメントに古いフラグメントの引数バンドルを渡すには、このタグ/ID で十分です。この二重性は紛らわしいですが、ハックも可能にします。コールバックのフラグメントの引数バンドルにonStop「キャンセル済み」フラグを設定できますonResume。これは、フラグが見つかった場合にそれ自体を却下するコールバックでのクエリです。そうすれば、概念的には AsyncTask に属し、それとともに終了する進行状況ダイアログを作成できます。

于 2012-10-02T10:09:54.710 に答える