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$2.run(FragmentManager.java:489)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
at android.support.v4.app.FragmentManagerImpl$1.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)
所以,我有一个使用 tabhost 构建的 Android 应用程序。总共三个选项卡,在tab2中,有一个按钮可以在tab2中进行fragment交易(也就是调用fragment Activity中的函数)
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.realtabcontent, mFrag);
t.addToBackStack(null);
t.commit();
如果我这样跑的话会有例外:
如何解决这个问题?感谢您的帮助
当我们尝试在关闭之前添加相同的片段或 DialogFragment 两次时,就会发生这种情况,
只需致电
if(mFragment.isAdded())
{
return; //or return false/true, based on where you are calling from
}
话虽如此,我不明白为什么要删除旧片段并再次添加相同的片段,因为我们可以通过简单地将参数传递给片段内的方法来更新 UI/数据
删除旧片段(如果仍然添加),然后添加新片段:
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");
您只需检查下面提到的片段中的一个条件:
if(!isAdded())
{
return;
}
isAdded = 如果片段当前已添加到其 Activity 中,则返回 true。 取自官方文档。
如果已经添加了该片段,则不会添加该片段
查看以下链接以获取参考:
http://developer.android.com/reference/android/app/Fragment.html#isAdded()
有时会发生这种情况,因为没有从相应的布局中找到正确的 id。我遇到了这个问题。然后几个小时后我发现我设置了错误的recyclerview id。我改变了它,对我来说效果很好。
因此,请仔细检查您的片段布局。
您只需在开始片段交易前检查一个条件
if (!fragmentOne.isAdded()){
transaction = manager.beginTransaction();
transaction.add(R.id.group,fragmentOne,"Fragment_One");
transaction.commit();
}
这对我来说非常有效......
你可以试试这个:
if (dialogFolderGallery.isAdded()) {
dialogFolderGallery.dismiss();
} else { //bla...bla..
}
当我没有将我的正文 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>
希望这可以帮助别人。
这是我的对话框片段解决方案(您也可以将这个概念用于片段类)
我尝试通过多次点击按钮快速单击显示对话框片段。
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");
}
对我来说,它的工作原理如下:
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();
如果您在
FragmentStatePagerAdapter
的 ViewPager
中创建了一个已经存在的项目,甚至可能会发生:
override fun getItem(position: Int): Fragment {
return tabs[0] // Right variant: tabs[position]
}
(
private val tabs: List<Fragment>
是选项卡中的片段列表)。
令我惊讶的是,我通过调用片段事务两次犯了愚蠢的错误:
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();
确保你不会犯同样的错误。
添加如下片段
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.realtabcontent, mFrag);
t.addToBackStack(null);
t.commitNowAllowingStateLoss();
当我在 Fragment 中错误地使用 ViewModel 时,出现此错误,如下所示:
//This is wrong!
MyViewModel viewModel = new MyViewModel(getActivity().getApplication());
正确做法:
viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(MyViewModel.class);
不好解决,但它有效)
if(!ConfirmDataSync.isVisible) show()
碎片交易是异步的。
在执行片段事务之前,您可能会两次或多次调用此代码。
!selectPlan04Dialog.isVisible() & !selectPlan04Dialog.isAdded()
条件是true
并且show()
安排另一个片段事务稍后执行。
解决此问题的一些选项:
executePendingTransactions()
videoOptionDialog.show(supportFragmentManager.beginTransaction().remove(videoOptionDialog),TrainingVideoMoreOptionDialog.TAG)
最好使用
commitNow()
进行交易。请参阅文档。
/**
* After a {@link FragmentTransaction} is committed with
* {@link FragmentTransaction#commit FragmentTransaction.commit()}, it
* is scheduled to be executed asynchronously on the process's main thread.
* If you want to immediately executing any such pending operations, you
* can call this function (only from the main thread) to do so. Note that
* all callbacks and other related behavior will be done from within this
* call, so be careful about where this is called from.
*
* <p>If you are committing a single transaction that does not modify the
* fragment back stack, strongly consider using
* {@link FragmentTransaction#commitNow()} instead. This can help avoid
* unwanted side effects when other code in your app has pending committed
* transactions that expect different timing.</p>
* <p>
* This also forces the start of any postponed Transactions where
* {@link Fragment#postponeEnterTransition()} has been called.
*
* @return Returns true if there were any pending transactions to be
* executed.
*/