Android IllegalStateException:已在tabhost片段中添加片段
所以,我有一个android应用程序,它是用tabhost构建的。总共有三个选项卡,在tab2中,有一个按钮用于在tab2中进行片段事务(它在片段活动中调用函数) 如果我这样运行,则会出现异常:Android IllegalStateException:已在tabhost片段中添加片段,android,android-fragments,tabs,android-lifecycle,fragment-tab-host,Android,Android Fragments,Tabs,Android Lifecycle,Fragment Tab Host,所以,我有一个android应用程序,它是用tabhost构建的。总共有三个选项卡,在tab2中,有一个按钮用于在tab2中进行片段事务(它在片段活动中调用函数) 如果我这样运行,则会出现异常: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_wi
<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>
如何解决这个问题?感谢您的帮助您只需检查下面提到的片段中的一个条件:
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.realtabcontent, mFrag);
t.addToBackStack(null);
t.commit();
isAdded=如果片段当前已添加到其活动中,则返回true。取自官方文档。
如果已添加该片段,则不会添加该片段查看下面的链接以获取参考:
当我们尝试在解除之前添加两次相同的片段或DialogFragment时,就会发生这种情况 就打电话
if(!isAdded())
{
return;
}
话虽如此,我看不出有任何理由删除旧片段并再次添加相同的片段,因为我们可以通过简单地将参数传递到片段内的方法来更新UI/数据。有时,由于没有从相应的布局中找到正确的id,会发生这种情况。我面临这个问题。很多小时后,我发现我设置了错误的recyclerview id。我更改了它,对我来说效果很好
所以,仔细检查你的片段布局 在启动片段事务之前,您只需检查一个条件
if(mFragment.isAdded())
{
return; //or return false/true, based on where you are calling from
}
这对我来说非常有效…如果仍然添加旧片段,请删除旧片段,然后添加新片段:
if (!fragmentOne.isAdded()){
transaction = manager.beginTransaction();
transaction.add(R.id.group,fragmentOne,"Fragment_One");
transaction.commit();
}
对我来说,它的工作原理如下:
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");
如果在
ViewPager
的FragmentStatePagerAdapter
中创建了一个已经存在的项目,甚至会发生这种情况:
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();
(
private val tabs:List
是选项卡中的片段列表)。令我惊讶的是,我犯了一个愚蠢的错误,调用了两次片段事务:
override fun getItem(position: Int): Fragment {
return tabs[0] // Right variant: tabs[position]
}
确保你没有犯同样的错误。按如下所示添加片段
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();
如果不在FrameLayout内的视图组中包装正文XML,则会出现此错误 错误:
if (dialogFolderGallery.isAdded()) {
dialogFolderGallery.dismiss();
} else { //bla...bla..
}
已解决:
<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>
希望这能帮助到其他人。我在片段中错误地使用ViewModel时出现了以下错误:
<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>
正确的方法:
//This is wrong!
MyViewModel viewModel = new MyViewModel(getActivity().getApplication());
这里是我的对话框片段解决方案(您也可以将此概念用于片段类) 我试着通过点击按钮多次快速点击显示对话框片段
viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(MyViewModel.class);
可能的重复意味着backpress添加了一个新片段,backbackback中的逻辑是什么?谢谢,除了tab2之外,还有一个lotis mFrag被添加到其他选项卡?谢谢你的帮助,你的意思是我把if(!isAdded())放在oncreateview中了吗?是的,你只需要把我在上面的回答中提到的代码放进去……这意味着你的片段已经添加到堆栈中了。所以,不需要再次添加它,它只返回简单的值。这毫无意义,您不能在onCreateView中返回void,您是说onCreate吗?我在那里尝试了这个,但它对我的问题没有帮助。这是添加到
onCreate
?为什么是否定符号?如果出现以下情况,不应该添加片段!isAdded()?这应该是公认的答案。被接受的答案毫无意义。首先,不应该对isAdded()
进行否定。其次,在注释中,建议将此代码放入onCreate()
,这也是毫无意义的。这行代码应该直接放在添加(或替换)片段的行之前,而不是放在onCreate()
或onCreateView()
中。在这两种方法中执行该代码已经太晚了。if(fragment.isAdded())fragmentTransaction.show(fragment)代码>也必须检查隐藏片段。我需要添加相似的片段,只有片段中的属性不同。但是重复的错误仍然发生。我已经实现了检查片段是否已经添加,然后返回(添加片段的代码将不会执行),因为我的应用程序在play store上运行,但我仍然得到了崩溃片段已经从一些设备中添加,而不是从一个月前我试图找到的所有设备中添加,我无法克服,我已经应用了大量的解决方案,并在live play store上更新了构建,但我仍然收到了一些设备的错误,如Galaxy S20+5G、华为,我收到的问题设备较少,如果有任何帮助,我将不胜感激。谢谢,对我来说也是如此。异常消息非常具有误导性。在调查根本原因一个多月后,这就是原因。谢谢,我们不应该发送参数来对已经显示的片段进行任何更改吗?在片段被添加到片段管理器之后,您不能设置参数,而不是再次删除和添加它。来自docs:“如果片段被添加到FragmentManager,并且isStateSaved()将返回true,则无法调用此方法。”因此,如果要更新UI,则需要直接调用片段方法。是的,我不是指通过setArguments设置,而是指将参数作为参数发送以进行更新,所以删除和添加相同的片段没有用,对吗?这取决于。如果你需要重新配置很多东西,用一个新的片段替换这个片段可能会更容易。这完全取决于您的需要。如果使用一个事务,我将继续接收错误。这可能是由于使用片段管理器的异步行为造成的?它会用新的替换旧的吗?不,它不会替换,它会将以前的片段添加到后堆栈中。我想知道,这可能吗?昨天我尝试了类似的代码,但出现了一个错误,请参阅,因为addToBackStack
不允许与commitNow
一起使用。在该链接中,他手动禁用了back
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");
}