Android IllegalStateException:片段已添加到 tabhost 片段中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25926402/
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
IllegalStateException: Fragment already added in the tabhost fragment
提问by user782104
FATAL EXCEPTION: main
Process: com.example.loan, PID: 24169
java.lang.IllegalStateException: Fragment already added: FormFragment{428f10c8 #1 id=0x7f050055 form}
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1192)
at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:722)
at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1533)
at android.support.v4.app.FragmentManagerImpl.run(FragmentManager.java:489)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
at android.support.v4.app.FragmentManagerImpl.run(FragmentManager.java:450)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
at dalvik.system.NativeStart.main(Native Method)
So, I have an android app that build with the tabhost. There are three tabs in total, in the tab2, there is a button to make the fragment transaction in tab2 (which is calling the function in the fragment activity)
所以,我有一个使用 tabhost 构建的 android 应用程序。一共有三个tabs,tab2里面有一个按钮,tab2里面有一个进行fragment事务的按钮(就是调用fragment活动中的函数)
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.realtabcontent, mFrag);
t.addToBackStack(null);
t.commit();
There is exception if I run like this:
如果我这样运行,则有例外:
- Inside the tab2, I press the button to change fragment
- Go to other tab (eg. tab 1 or tab 3)
- Press back button
- Throw exception
- 在tab2里面,我按下按钮来改变片段
- 转到其他选项卡(例如选项卡 1 或选项卡 3)
- 按返回键
- 抛出异常
How to fix that? Thanks for helping
如何解决?谢谢你的帮助
回答by Ujju
This happens when we try to add same fragment or DialogFragment twice before dismissing,
当我们尝试在关闭之前两次添加相同的片段或 DialogFragment 时会发生这种情况,
just call
打电话
if(mFragment.isAdded())
{
return; //or return false/true, based on where you are calling from
}
Having said that, I don't see any reason why to remove old fragment and add the same fragment again since we can update the UI/data by simply passing parameters to the method inside the fragment
话虽如此,我看不出有任何理由删除旧片段并再次添加相同的片段,因为我们可以通过简单地将参数传递给片段内的方法来更新 UI/数据
回答by vovahost
Remove the old fragment in case it is still added and then add the new fragment:
如果仍然添加旧片段,请删除旧片段,然后添加新片段:
FragmentManager fm = getSupportFragmentManager();
Fragment oldFragment = fm.findFragmentByTag("fragment_tag");
if (oldFragment != null) {
fm.beginTransaction().remove(oldFragment).commit();
}
MyFragment newFragment = new MyFragment();
fm.beginTransaction().add(newFragment , "fragment_tag");
回答by Deep Mehta
You just have to check one condition in your fragment mentioned below:
您只需要检查下面提到的片段中的一个条件:
if(!isAdded())
{
return;
}
isAdded = Return true if the fragment is currently added to its activity.Taken from the official document.
This will not add that fragment if it is already added
isAdded = 如果片段当前已添加到其活动中,则返回 true。摘自官方文档。如果已添加该片段,则不会添加该片段
Check below link for a reference:
http://developer.android.com/reference/android/app/Fragment.html#isAdded()
检查以下链接以获取参考:http:
//developer.android.com/reference/android/app/Fragment.html#isAdded()
回答by Mehul Solanki
You just have to check one condition before start fragment transaction
您只需要在开始片段事务之前检查一个条件
if (!fragmentOne.isAdded()){
transaction = manager.beginTransaction();
transaction.add(R.id.group,fragmentOne,"Fragment_One");
transaction.commit();
}
this is working perfactly for me...
这对我来说非常有效......
回答by Mihab
Sometimes it happens for not finding proper id from the respective layout. I faced this problem. Then after many hours I found that I set wrong recyclerview id. I change it, and works fine for me.
有时会因为没有从相应的布局中找到正确的 id 而发生。我遇到了这个问题。几个小时后,我发现我设置了错误的 recyclerview id。我改变了它,对我来说很好用。
So, double check your fragment layout.
因此,请仔细检查您的片段布局。
回答by Dung Nguyen
I have this error when not wrapping my body XML inside a ViewGroup inside FrameLayout.
没有将我的正文 XML 包装在 FrameLayout 内的 ViewGroup 中时,出现此错误。
Error:
错误:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".screens.home.HomeEpoxyFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:overScrollMode="never"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout>
Solved:
解决了:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".screens.home.HomeEpoxyFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:overScrollMode="never"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Hope this may help someone.
希望这可以帮助某人。
回答by Farid Haq
For me it works like:
对我来说,它的工作原理是:
Fragment oldFragment = manager.findFragmentByTag(READER_VIEW_POPUP);
if (oldFragment != null) {
manager.beginTransaction().remove(oldFragment).commit();
}
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
回答by CoolMind
It even can occur if in FragmentStatePagerAdapter
of your ViewPager
you create an item that already exists:
它如果偶可发生FragmentStatePagerAdapter
的你ViewPager
,你创建一个已经存在的项目:
override fun getItem(position: Int): Fragment {
return tabs[0] // Right variant: tabs[position]
}
(private val tabs: List<Fragment>
is a list of fragments in tabs).
(private val tabs: List<Fragment>
是选项卡中的片段列表)。
回答by Seto Elkahfi
To my surprise, I made stupid mistake by calling the fragment transaction twice:
令我惊讶的是,我通过两次调用片段交易犯了一个愚蠢的错误:
if (!FirebaseManager.isClientA && !FirebaseManager.isClientB) {
fragment = new FragmentA();
getFragmentManager().beginTransaction().add(R.id.fragment_frame, fragment, null).addToBackStack("").commit();
} else if (FirebaseManager.isClientB) {
fragment = new FragmentB();
} else {
fragment = new FragmentC();
}
getFragmentManager().beginTransaction().add(R.id.fragment_frame, fragment, null).addToBackStack("").commit();
Make sure you don't make the same mistake.
确保你不会犯同样的错误。
回答by M.Noman
Add Fragment as below
添加片段如下
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.realtabcontent, mFrag);
t.addToBackStack(null);
t.commitNowAllowingStateLoss();