IllegalStateException:片段已添加到tabhost片段中

时间:2014-09-19 04:30:01

标签: android android-fragments tabs android-lifecycle fragment-tab-host

09-19 12:23:01.084: E/AndroidRuntime(24169): FATAL EXCEPTION: main
09-19 12:23:01.084: E/AndroidRuntime(24169): Process: com.example.loan, PID: 24169
09-19 12:23:01.084: E/AndroidRuntime(24169): java.lang.IllegalStateException: Fragment already added: FormFragment{428f10c8 #1 id=0x7f050055 form}
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1192)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:722)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1533)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.support.v4.app.FragmentManagerImpl$2.run(FragmentManager.java:489)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:450)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.os.Handler.handleCallback(Handler.java:733)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.os.Handler.dispatchMessage(Handler.java:95)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.os.Looper.loop(Looper.java:136)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at android.app.ActivityThread.main(ActivityThread.java:5068)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at java.lang.reflect.Method.invokeNative(Native Method)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at java.lang.reflect.Method.invoke(Method.java:515)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
09-19 12:23:01.084: E/AndroidRuntime(24169):    at dalvik.system.NativeStart.main(Native Method)

所以,我有一个用tabhost构建的android应用程序。共有三个选项卡,在tab2中,有一个按钮用于在tab2中进行片段事务(在片段活动中调用该函数)

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.realtabcontent, mFrag);
        t.addToBackStack(null);
        t.commit();

如果我像这样跑,有例外:

  1. 在tab2内,我按下按钮更改片段
  2. 转到其他标签(例如标签1或标签3)
  3. 按后退按钮
  4. 抛出异常
  5. 如何解决这个问题?谢谢你的帮助

13 个答案:

答案 0 :(得分:108)

当我们尝试在解雇之前添加相同的片段或DialogFragment两次时会发生这种情况,

只需致电

if(mFragment.isAdded())
{
     return; //or return false/true, based on where you are calling from
}

话虽如此,我没有看到任何理由为什么要删除旧片段并再次添加相同的片段,因为我们可以通过简单地将参数传递给片段内的方法来更新UI /数据

答案 1 :(得分:7)

您只需检查下面提到的片段中的一个条件:

if(!isAdded())
{
    return;
}

isAdded =如果片段当前已添加到其活动中,则返回true。取自官方文档。 如果已经添加了该片段,则不会添加该片段

请查看以下链接以获取参考:
http://developer.android.com/reference/android/app/Fragment.html#isAdded()

答案 2 :(得分:7)

删除旧片段,以防它仍然添加,然后添加新片段:

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");

答案 3 :(得分:5)

您必须在开始片段交易之前检查一个条件

 if (!fragmentOne.isAdded()){
            transaction = manager.beginTransaction();
            transaction.add(R.id.group,fragmentOne,"Fragment_One");
            transaction.commit();
 }

这对我有用......

答案 4 :(得分:1)

有时会因为没有从相应的布局中找到正确的ID而发生。我遇到了这个问题。然后几个小时后我发现我设置了错误的recyclerview id。我改变它,对我来说很好。

因此,请仔细检查您的片段布局。

答案 5 :(得分:1)

不将我的主体XML封装在FrameLayout的ViewGroup中时出现此错误。

错误:

<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>

已解决:

<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>

希望这可能对某人有所帮助。

答案 6 :(得分:0)

对我来说,它的工作原理是:

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();

答案 7 :(得分:0)

如果您在FragmentStatePagerAdapter的{​​{1}}中创建了一个已经存在的商品,甚至可能会发生:

ViewPager

({override fun getItem(position: Int): Fragment { return tabs[0] // Right variant: tabs[position] } 是选项卡中的片段列表)。

答案 8 :(得分:0)

令我惊讶的是,我两次调用了片段事务,犯了一个愚蠢的错误:

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();

确保您没有犯同样的错误。

答案 9 :(得分:0)

添加如下片段

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.replace(R.id.realtabcontent, mFrag);
    t.addToBackStack(null);
    t.commitNowAllowingStateLoss();

答案 10 :(得分:0)

您可以尝试以下方法:

 if (dialogFolderGallery.isAdded()) {
                dialogFolderGallery.dismiss();
            } else { //bla...bla..
}

答案 11 :(得分:0)

我在 Fragment 中错误地使用了我的 ViewModel 时遇到了这个错误:

//This is wrong!
MyViewModel viewModel = new MyViewModel(getActivity().getApplication());

正确方法:

viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(MyViewModel.class);

答案 12 :(得分:0)

这里是我的 Dialog Fragment 解决方案(您也可以将这个概念用于片段类)

我尝试通过多次快速点击按钮来单击显示对话框片段。

            FragmentManager fm = getSupportFragmentManager();
            Fragment oldFragment = fm.findFragmentByTag("wait_modal");

            if(oldFragment != null && oldFragment.isAdded())
                return;

            if(oldFragment == null && !please_wait_modal.isAdded() && !please_wait_modal.isVisible()){
                fm.executePendingTransactions();
                please_wait_modal.show(fm,"wait_modal");
            }