java.lang.IllegalStateException:已添加片段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19441932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.IllegalStateException: Fragment already added
提问by creaity
I have a Problem with a Android App compiled and running with target SDK 4.3. The App has two Activities, a MainActivity which is also the Launcher Activity and a SecondActivity. Both are using Fragments. To Support older Devices also, the support lib is used.
我有一个使用目标 SDK 4.3 编译和运行的 Android 应用程序的问题。该应用程序有两个 Activity,一个 MainActivity 也是 Launcher Activity 和一个 SecondActivity。两者都使用片段。为了也支持旧设备,使用了支持库。
In the following scenario it comes to the "IllegalStateException: Fragment already added" Error.
在以下场景中,会出现“IllegalStateException: Fragment already added”错误。
1) Start the app -> MainActivity is shown
2) switch to the SecondActivity with an Intent
3) Press the Home Button
4) Wait a longer time (tested with 24 hours)
5) press again the app icon -> Exception. If the time is shorter, the SecondActivity is shown like expected.
1) 启动应用程序 -> MainActivity 显示
2) 切换到带有 Intent 的 SecondActivity
3) 按下主页按钮
4) 等待更长的时间(测试 24 小时)
5)再次按下应用程序图标 -> 异常。如果时间更短,SecondActivity 将按预期显示。
I have read a lot of the IllegalStateExceptions during Fragment handling, but all all of them pointed to a problem with a replace() method. In the Stacktrace, my own code is never called.
我在 Fragment 处理期间阅读了很多 IllegalStateExceptions,但所有这些都指出了 replace() 方法的问题。在 Stacktrace 中,我自己的代码从未被调用。
The Fragement is added in the Activies onCreate() Method:
在 Activies onCreate() 方法中添加 Fragment:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(..);
ListFragment listFragment = this.getCaptureListFragment();
FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
tx.add(R.id.MainFragmentContainer, listFragment, "list_fragment_tag");
tx.commit();
}
private ListFragment getListFragment() {
ListFragment listFragment = (ListFragment) this.getSupportFragmentManager().findFragmentByTag("list_fragment_tag");
if (listFragment == null) {
listFragment = new ListFragment();
}
return listFragment;
}
java.lang.RuntimeException: Unable to start activity ComponentInfo{de.myexample.demo/de.myexample.demo.ui.SecondActivity}: java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment}
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
at android.app.ActivityThread.access0(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment}
at android.support.v4.app.FragmentManagerImpl.addFragment(SourceFile:1175)
at android.support.v4.app.BackStackRecord.run(SourceFile:616)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1460)
at android.support.v4.app.FragmentActivity.onStart(SourceFile:556)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5143)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
... 11 more
java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment}
at android.support.v4.app.FragmentManagerImpl.addFragment(SourceFile:1175)
at android.support.v4.app.BackStackRecord.run(SourceFile:616)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1460)
at android.support.v4.app.FragmentActivity.onStart(SourceFile:556)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5143)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
at android.app.ActivityThread.access0(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
采纳答案by creaity
Okay, solved in on my own.
好的,我自己解决了。
I put all Fragments out in onPause() and store the state in some booleans. Depending on that booleans the Fragments are put in in onResume(). Than the launch is stable regardless how long the Activity was in the background.
我将所有 Fragment 放入 onPause() 并将状态存储在一些布尔值中。根据那个布尔值,片段被放入 onResume()。无论 Activity 在后台运行多长时间,启动都是稳定的。
boolean addList = false;
@Override
protected void onResume() {
FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
if (this.addList) {
ListFragment list = this.getListFragment();
tx.add(R.id.MainFragmentContainer, list, "list_fragment_tag");
}
tx.commit();
super.onResume();
this.addList = false;
}
@Override
protected void onPause() {
this.addList = this.getListFragment().isAdded();
...
if (this.addList) {
FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
tx.remove(this.getListFragment());
tx.commit();
}
this.getSupportFragmentManager().executePendingTransactions();
super.onPause();
}
Maybe that helps someone with the same problem
也许这可以帮助有同样问题的人
回答by Hyman Feng
The Fragment manager saves its state when exit. So you don't have to add your fragment again.
Fragment 管理器在退出时保存其状态。所以你不必再次添加你的片段。
Do like this:
这样做:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(..);
if (savedInstanceState == null) {
ListFragment listFragment = this.getCaptureListFragment();
FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
tx.add(R.id.MainFragmentContainer, listFragment, "list_fragment_tag");
tx.commit();
}
}
回答by Andy
In order to reproduce this, one could activate "Don't keep activities" in Settings -> Developer options. Then pause and resume the activity.
为了重现这一点,可以在“设置”->“开发人员选项”中激活“不要保留活动”。然后暂停并恢复活动。
That's so you don't have to wait 24 hours :)
这样您就不必等待 24 小时 :)
回答by serefakyuz
It is not necessary to create new boolean field for checking fragment's adding state. There is also a method in fragment.
Just use it:
myFragment.isAdded()
没有必要创建新的布尔字段来检查片段的添加状态。片段中还有一个方法。
只需使用它:
myFragment.isAdded()