1

我正在使用 Android 支持库 (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(findFragmentByTag返回 null)。我对此感到困惑。showProgressDialog该标签是我的实现活动中的静态字符串,因此在调用和之间不会丢失或更改它closeDialog

任何想法/提示/建议将不胜感激。

谢谢。

4

1 回答 1

8

问题是我正在取消AsyncTask活动中的onDestroy. 这可以摆脱 bg 线程,但AsyncTask.onCancelled没有地方关闭片段,因为它在活动被破坏后运行。在此之前,会创建一个新活动,并且片段管理器会恢复一个新对话框(即使它是使用 创建的setRetainInstance(false),我猜这是默认设置)。

通话时间线是这样的:

  1. 屏幕旋转触发配置更改
  2. 旧活动进入onDestroy,取消异步任务。
  3. 旧对话框进入onDetach
  4. 新活动被创建。
  5. 创建新对话框,附加到新活动并显示。
  6. 旧任务onCancel执行,调用closeDialog,但未找到标记。

我的错误是假设字符串标签在应用程序上下文中全局识别了一个片段,但事实证明,片段管理器分配的实际片段 ID 是片段标签/ID 及其活动 ID 的组合。当 Activity 被销毁时,它们的 Fragment 被分离,并且在此之后,即使具有相同标签/ID 的新 Fragment 在前台,因为它附加到不同的 Activity,当旧的 Activity 时,Fragment Manager 会返回 null调用 findFragmentByTag。

然而,这个标签/id 足以让新片段传递旧片段的参数包。这种二元性令人困惑,但它也启用了一个 hack:我们可以在其回调中使用“已取消”标志填充片段的参数包,在onStop回调中查询它,onResume如果找到标志,它会调用解除自身。这样我就可以有一个概念上属于 AsyncTask 的进度对话框,并随之消亡。

于 2012-10-02T10:09:54.710 回答