FragmentManager.findFragmentByTag返回null(FragmentMa

2019-09-23 06:56发布

我使用的是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)。 我很困惑与此有关。 标记是我在执行活动的静态字符串,所以没有什么指望的调用之间丢失或改变showProgressDialogcloseDialog

任何想法/提示/建议将非常感激。

谢谢。

Answer 1:

问题是,我取消AsyncTask在活动的onDestroy 。 这是确定摆脱BG线程,但AsyncTask.onCancelled是无处关闭一个片段,因为它运行后的活动已被破坏。 在此之前,一个新的活动被创建,和碎片经理恢复一个新的对话框(即使它与创建setRetainInstance(false) ,我的猜测是默认值)。

通话的时间表是这样的:

  1. 屏幕旋转触发配置变化
  2. 老年活动进入onDestroy ,取消的AsyncTask。
  3. 老对话进入onDetach
  4. 新活动创建。
  5. 新的对话框被创建,被连接到新的活动和显示。
  6. 老任务onCancel执行,来电closeDialog ,但标签未找到。

我的错误是假设在应用程序上下文识别的片段全局字符串变量,但事实证明,由片断经理交办的实际片段ID是片段标签/ ID和活动ID的组合。 当活动被销毁,他们的片段被分离,而这一点后,即使使用相同的标记/ ID的新片段是在前台,因为它是连接到一个不同的活动,片段管理器返回空的时候,老活动调用findFragmentByTag。

然而这个标签/ ID是不够的新片段传递旧片段的论点束。 这种双重性是混乱的,但它也使黑客:我们可以填充片段的参数捆绑在其onStop与“取消”的标志,它在一个查询回调onResume回调,它呼吁解散本身如果该标志是找到。 这样我可以有一个概念上属于的AsyncTask,并用它死进度对话框。



文章来源: FragmentManager.findFragmentByTag returns null