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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:50:29  来源:igfitidea点击:

IllegalStateException: Fragment already added in the tabhost fragment

androidandroid-fragmentstabsandroid-lifecyclefragment-tab-host

提问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:

如果我这样运行,则有例外:

  1. Inside the tab2, I press the button to change fragment
  2. Go to other tab (eg. tab 1 or tab 3)
  3. Press back button
  4. Throw exception
  1. 在tab2里面,我按下按钮来改变片段
  2. 转到其他选项卡(例如选项卡 1 或选项卡 3)
  3. 按返回键
  4. 抛出异常

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 FragmentStatePagerAdapterof your ViewPageryou 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();