我怎样才能预防;java.lang.IllegalStateException:已添加片段";更换碎片时?
尽管我努力防止片段被多次添加,但仍然会遇到我怎样才能预防;java.lang.IllegalStateException:已添加片段";更换碎片时?,java,android,android-fragments,Java,Android,Android Fragments,尽管我努力防止片段被多次添加,但仍然会遇到java.lang.IllegalStateException:Fragment ready added:VideoFragment 我有一个活动,其中VideoFragment仅在onCreate中实例化。在我试图显示视频片段的唯一地方,我首先检查是否已经添加了该片段 private VideoFragment videoFragment; public void onCreate(Bundle savedInstanceState) { .
java.lang.IllegalStateException:Fragment ready added:VideoFragment
我有一个活动,其中VideoFragment仅在onCreate中实例化。在我试图显示视频片段的唯一地方,我首先检查是否已经添加了该片段
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:Fragment已添加:VideoFragment
,用于用户,堆栈跟踪由Android类组成
/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
added inisAdded()
的定义是否与用于检查片段事务的定义不匹配
或者活动中的视频片段引用是否有不同的方式?这是保存状态时需要显式处理的问题吗
或者是否有可靠的替代方法来检查片段是否已经添加
更新 我已经想出了如何半可靠地产生这个问题
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()代码>和片段优先级2=getFragmentManager().findFragmentById(R.id.Fragment\u容器)在运行replace fragment事务之前执行code>,但这些事务出现null
事实上,我的问题看起来很相似
虽然时间看起来不像内存/缓存效果那么重要。我完全不清楚为什么这个问题被解决了
我将尝试生成一个简单的应用程序来复制这个问题。我当前的一个使用webrtc,而logcat输出中完全充斥着webrtc消息 我在这里看到了一些东西:
当系统重新创建活动时,可能会出现问题。您只需更改设备方向即可完成此操作
isAdded()
返回false
,因为已重新创建了活动
,因此此方法用于不知道以前添加内容的视频片段
的新安装
showVideoFragment()
实际上是将片段添加到活动中,而不是仅仅显示它。我建议您将该方法重命名为类似“addVideoFragment”的名称,并将其移动到onCreate()
方法如果这样做,您就可以解决问题。
如果确实要显示或隐藏片段,请使用FragmentTransaction
中的方法,例如:
FragmentManager fm = getFragmentManager();
fm.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.show(somefrag) // or hide
.commit();
提示:
当您事先知道您的片段始终是视频片段时,您可以简单地使用:
<fragment
android:name="com.example.VideoFragment"
android:id="@+id/video_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
用这个实例做你想要的任何东西 我想我已经成功地修复了这个错误,通过尝试在一个更简单的例子中重现这个错误:
我犯了一个错误,在对onCreate
的连续调用中添加了一个片段的多个实例(而不是视频片段),这是由活动的重新创建引起的。此片段添加没有触发java.lang.IllegalStateException:fragment ready added
,因为显然,只有尝试多次添加同一片段实例,而不是同一片段的多个实例时,才会发生这种情况
调用fragmentreplace
方法后,将为新的VideoFragment生成java.lang.IllegalStateException:fragment ready added
,即使使用replace只添加一次VideoFragment
通过确保只添加一次不同的片段,替换为VideoFragment将不再生成java.lang.IllegalStateException:fragment ready added:VideoFragment
,至少对于上文所述的复制步骤是如此。IllegalStateException似乎与添加/替换视频片段无关,而是与被替换片段的状态有关
我对这项决议感到不满,原因有二:
错误消息具有误导性。它说视频片段已经被添加,我已经解决了这个问题,确保不同的片段不会被添加多次,这不会产生异常
replace
文档具有很大的误导性。根据我的阅读,在调用replace之前,片段容器的状态应该是什么并不重要;结束状态应该完全由从replace参数添加的片段确定。我认为这种差异在相关问题中最为明显,尽管该问题的回答者不同意
替换添加到容器中的现有片段。这本质上与为所有当前添加的片段调用remove(Fragment)相同,这些片段是使用相同的containerWebID添加的,然后使用此处给出的相同参数添加(int、Fragment、String)
您是否有可靠再现此错误的特定配方?换句话说,用户采取了哪些步骤导致崩溃?丢失
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_layout);
VideoFragment fragment = (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragmen);
}