如何防止"java.lang.IllegalStateException:片段已添加"更换碎片时? [英] How can I prevent "java.lang.IllegalStateException: Fragment already added" when replacing fragments?

查看:136
本文介绍了如何防止"java.lang.IllegalStateException:片段已添加"更换碎片时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管我努力防止多次添加片段,但我仍然遇到 java.lang.IllegalStateException:片段已添加:VideoFragment .

Despite my efforts to prevent fragments from being added more than once, I continue to encounter java.lang.IllegalStateException: Fragment already added: VideoFragment.

我有一个活动,其中VideoFragment仅在onCreate上实例化.在试图显示VideoFragment的唯一地方,我首先检查该片段是否已经添加.

I have an activity where VideoFragment is instantiated in onCreate only. In the only place I attempt to display the VideoFragment, I first check whether this fragment has been added already.

private VideoFragment videoFragment;

public void onCreate(Bundle savedInstanceState) {
    ...
    videoFragment = new VideoFragment();
    ...
}

private void showVideoFragment() {
    if (!videoFragment.isAdded()) {
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, videoFragment, "video").commit();
    }
}

我一直无法始终如一地重现此问题,以在调试器中进行检查,但是我的运行时错误报告继续报告异常 java.lang.IllegalStateException:已为用户添加片段:VideoFragment ,包含由Android类组成的堆栈跟踪.

I have not been able to consistently reproduce this problem to examine in the debugger, but my runtime error reporting continues to report the exception java.lang.IllegalStateException: Fragment already added: VideoFragment for users, with stack traces composed of Android classes.

/FragmentManager.java:1133→ android.app.FragmentManagerImpl.addFragment
/BackStackRecord.java:648→ android.app.BackStackRecord.run
/FragmentManager.java:1453→ android.app.FragmentManagerImpl.execPendingActions
/FragmentManager.java:443→ android.app.FragmentManagerImpl$1.run
/Handler.java:733→ android.os.Handler.handleCallback
/Handler.java:95→ android.os.Handler.dispatchMessage
/Looper.java:146→ android.os.Looper.loop
/ActivityThread.java:5487→ android.app.ActivityThread.main
/Method.java:-2→ java.lang.reflect.Method.invokeNative
/Method.java:515→ java.lang.reflect.Method.invoke
/ZygoteInit.java:1283→ com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
/ZygoteInit.java:1099→ com.android.internal.os.ZygoteInit.main
/NativeStart.java:-2→ dalvik.system.NativeStart.main

i☎联系人()中添加的定义是否与检查片段交易使用的定义不匹配?

Does the definition of added in isAdded() not match the one used to check fragment transactions?

或者活动中的videoFragment引用是否有某种不同的方式?保存状态 http://developer.android时,我需要明确处理此问题.com/guide/components/activities.html#SavingActivityState ?

Or is there some way the videoFragment reference in the activity is not the same? Is this something I need to explicitly handle when saving state http://developer.android.com/guide/components/activities.html#SavingActivityState?

还是有一种可靠的替代方法来检查片段是否已添加?

Or is there a reliable alternative way of checking whether the fragment has already been added?

更新

我已经弄清楚了如何半可靠地产生这个问题.

I have figured out how to semi-reliably produce the problem.

  1. 启动应用程序
  2. 导航远离应用程序,并暂时运行其他程序.在我的Galaxy Nexus(近来这很慢)上,使用Chrome阅读几则新闻似乎就足够了.返回主屏幕时,如果需要花费几秒钟的时间进行渲染,则应用程序可能会抛出片段异常.
  3. 重新启动应用程序并触发片段更改

如果我杀死并只是运行该应用程序,一切似乎都很好.或者,如果我离开该应用程序并立即返回,则可以正常工作.只有将应用程序在后台保留一小段时间(足以从内存中删除吗?)时,才会出现碎片问题.

If I kill and simply run the application, everything appears to be fine. Or if I navigate away from the application and come back immediately, it works okay. It's only if the application is left in the background for a bit (enough to remove from memory?), that the fragment issue appears.

我也没有尝试过onCreate

I also tried, to no effect, in onCreate

View v = findViewById(R.id.fragment_container);
if(v != null){
    Log.d(TAG, "disabling save for fragment_container");
    v.setSaveEnabled(false);
    v.setSaveFromParentEnabled(false);
}

我还尝试检查 Fragment Prior = getFragmentManager().findFragmentByTag("video"); Fragment Prior2 = getFragmentManager().findFragmentById(R.id.fragment_container); 在运行替换片段事务之前,但是这些出现 null .

I also tried checking Fragment prior = getFragmentManager().findFragmentByTag("video"); and Fragment prior2 = getFragmentManager().findFragmentById(R.id.fragment_container); before running the replace fragment transaction, but these come up null.

我的问题实际上看起来与 https://code.google.com/p/android/issues/detail?id = 61247 尽管时间似乎不如内存/缓存影响那么大.我完全不清楚为什么这个问题已经解决.

My problem in fact looks very similar to https://code.google.com/p/android/issues/detail?id=61247 though the time appears less an issue than memory/cache effects. It is completely unclear to me why that issue was closed.

我将尝试生成一个简单的应用程序来复制此问题.我当前使用的是webrtc,而logcat的输出完全被webrtc消息所困扰.

I will try to produce a simple application that replicates this issue. My current one uses webrtc, and the logcat output is completely cluttered with webrtc messages.

推荐答案

我认为通过尝试在一个更简单的示例中重现此错误,我已经成功解决了该错误: https://stackoverflow.com/a/30672516/4107809

I think I have successfully fixed this error, by trying to reproduce this in a simpler example: https://stackoverflow.com/a/30672516/4107809

我犯了一个错误,即由于重新创建Activity而在连续调用 onCreate 的过程中添加了片段的多个实例(不是VideoFragment).片段的添加并未触发 java.lang.IllegalStateException:片段已添加,因为显然,只有当您尝试多次添加同一片段实例而不是同一片段的多个实例时,才会发生这种情况.

I was making a mistake where multiple instances of a fragment (not the VideoFragment) were added in successive calls to onCreate caused by recreation of the Activity. This fragment addition did not trigger the java.lang.IllegalStateException: Fragment already added because apparently this happens only if you try to add the same fragment instance more than once, not multiple instances of the same fragment.

调用片段 replace 方法后,即使新VideoFragment仅使用一次添加一次,但也会为新的VideoFragment生成 java.lang.IllegalStateException:已经添加的片段.代替.

Upon calling the fragment replace method, the java.lang.IllegalStateException: Fragment already added is generated for the new VideoFragment, even though the VideoFragment is only added once using replace.

通过确保仅添加一次不同的片段,由VideoFragment进行的替换不再生成 java.lang.IllegalStateException:已经添加的片段:VideoFragment ,至少对于上面概述的再现步骤.IllegalStateException似乎与添加/替换VideoFragment没有关系,但是与被替换的片段的状态无关.

By ensuring the different fragment was added only once, the replace by the VideoFragment no longer generates java.lang.IllegalStateException: Fragment already added: VideoFragment, at least for the steps for reproducing I outlined above. The IllegalStateException appears to have nothing to do with adding/replacing the VideoFragment, but with the state of the fragments being replaced.

我对该决议感到不满意的原因有两个:

I am displeased by this resolution for two reasons:

  1. 该错误消息具有误导性.它说已经添加了VideoFragment,我已经解决了这一问题,方法是确保不重复添加一个不同的片段,而不会产生异常.

  1. The error message is misleading. It says the VideoFragment has already been added, and I have resolved this by making sure that a different fragment is not added more than once, which did not generate an exception.

replace 文档非常容易引起误解.根据我的阅读,在调用replace之前片段容器的状态是什么都没关系;结束状态应仅由从replace参数添加的片段确定.我认为这种差异在链接的问题中最明显,尽管该问题的回答者不同意.

The replace documentation is very misleading. Based on my reading, it should not matter what the state of the fragment container is prior to calling to replace; the end state should be determined solely by the fragment that is added from the replace argument. I think this discrepancy is most clear in the linked question, though the answerer in that question disagrees.

替换添加到容器中的现有片段.这与在使用相同的containerViewId之后添加的所有当前添加的片段调用remove(Fragment)相同,然后使用此处给出的相同参数调用add(int,Fragment,String).

Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

这篇关于如何防止"java.lang.IllegalStateException:片段已添加"更换碎片时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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