FragmentManager.findFragmentByTag返回null [英] FragmentManager.findFragmentByTag returns null

查看:2352
本文介绍了FragmentManager.findFragmentByTag返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Android的支持库(V4)和ActionBarSherlock。我试图关闭进度对话框编程。我有codeD的小工具类,以帮助对话管理。

I'm using Android Support Library (v4) and ActionBarSherlock. I'm trying to close a progress dialog programatically. I've coded a small utility class to help with dialog management.

对话是从 AsyncTask.on preExecute 所示。它得到正确显示。然后我火通过旋转装置,它破坏活性的配置变化(调用的onDestroy AsyncTask.cancel(真))。 AsyncTask.onCancelled 被调用,在这个方法,其中我试图关闭对话框。但没有任何反应。下面是辅助功能显示和关闭对话框:

The dialog is shown from an AsyncTask.onPreExecute. It gets displayed correctly. Then I fire a config change by rotating the device, which destroys the activity (onDestroy calls AsyncTask.cancel(true)). AsyncTask.onCancelled is called, and is in this method where I'm trying to close the dialog. But nothing happens. Here are the helper functions to show and close the dialog:

    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的被取消。我打电话 closeDielog onPostExecute ,也从 onCancelled 。对话永远不会被关闭,因为标签的ID找不到( findFragmentByTag 返回null)。我很困惑与此有关。标签是我在执行活动的静态字符串,所以没有什么指望了丢失或调用之间更改为 showProgressDialog closeDialog

After rotating the device, the AsyncTask is cancelled. I'm calling closeDielog from onPostExecute and also from onCancelled. The dialog never gets closed because the tag ID is not found (findFragmentByTag returns null). I'm puzzled with this. The tag is a static String in my implementation activity so there's no chance of it being lost or changed between the calls to showProgressDialog and closeDialog.

任何想法/提示/建议将大大AP preciated。

Any idea/hint/suggestion will be much appreciated.

感谢。

推荐答案

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

The problem is that I'm cancelling the AsyncTask in the activity's onDestroy. This is ok to get rid of the bg thread, but AsyncTask.onCancelled is no place to close a fragment, because it runs AFTER the activity has been destroyed. Before that, a new activity is created, and the fragment manager restores a new dialog (even if it was created with setRetainInstance(false), which I guess is the default).

调用的时间表是这样的:

The timeline of calls is something like this:


  1. 屏幕旋转触发配置变化

  2. 老年活动进入的onDestroy ,取消AsyncTask的。

  3. 旧对话框中输入 onDetach

  4. 新的活动被创建。

  5. 创建新的对话框,被附加到新的活动,所示。

  6. 旧任务 onCancel 执行,要求 closeDialog ,但标签未找到。

  1. screen rotation triggers a config change
  2. old activity enters onDestroy, cancels the asynctask.
  3. old dialog enters onDetach.
  4. new activity is created.
  5. new dialog is created, gets attached to new activity and is shown.
  6. the old task onCancel executes, calls closeDialog, but the tag is not found.

我的错误是假设在应用程序上下文确定的片段在全球范围字符串变量,但事实证明,通过片段经理交办的实际片段ID是片段标记/ ID和活动ID的组合。当活动被破坏时,它们的片段被分离,并在这之后,即使使用相同的标记/标识一个​​新的片段是在前景,因为它被连接到一个不同的活动,该片段管理器返回null时老活性调用findFragmentByTag。

My error was assuming the string tag identified a fragment globally in the application context, but it turns out that the actual fragment ID assigned by the fragment manager is a combination of fragment tag/id and its activity id. When the activity is destroyed, their fragments are detached, and after this point, even if a new fragment with the same tag/id is in the foreground, as it is attached to a different activity, the fragment manager returns null when the old activity calls findFragmentByTag.

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

However this tag/id is enough for the new fragment to be passed the arguments bundle of the old fragment. This duality is confusing, but it also enables a hack: We can populate the arguments bundle of the fragment in its onStop callback with a "cancelled" flag, an query about it in the onResume callback, where it calls dismiss itself if the flag is found. That way I can have a progress dialog that conceptually belongs to the AsyncTask, and dies with it.

这篇关于FragmentManager.findFragmentByTag返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆