Android 在底部选项卡导航中将嵌套片段重新附加到其片段容器时,嵌套片段的状态将丢失
我正在开发具有以下UI结构的应用程序:Android 在底部选项卡导航中将嵌套片段重新附加到其片段容器时,嵌套片段的状态将丢失,android,android-fragments,android-lifecycle,android-nested-fragment,fragmentmanager,Android,Android Fragments,Android Lifecycle,Android Nested Fragment,Fragmentmanager,我正在开发具有以下UI结构的应用程序: 一个名为FoodActivity的活动 此活动执行。因此,可以显示三类食物:水果、肉和鱼 活动有一个大的片段容器,当用户与底部选项卡交互时,我将水果、肉和鱼的片段附在容器中 每个外部片段(鱼、肉和鱼)显示片段之间的导航:它可以显示水果列表以及所选水果的详细信息。 因此,外部Fragments有另一个Fragments容器,我将Fragments附加在其中,用于水果列表或水果细节 因此,它是一个主要的活动,它有一个很大的片段容器,我在其中交换片段
- 一个名为FoodActivity的
活动
- 此
活动执行。因此,可以显示三类食物:水果、肉和鱼
有一个大的活动
容器,当用户与底部选项卡交互时,我将水果、肉和鱼的片段
片段附在容器中
- 此
- 每个外部
(鱼、肉和鱼)显示片段
片段之间的导航:它可以显示水果列表以及所选水果的详细信息。
- 因此,外部
有另一个Fragments
容器,我将Fragments
附加在其中,用于水果列表或水果细节李>Fragments
- 因此,外部
活动
,它有一个很大的片段
容器,我在其中交换片段
,而这些片段又嵌套了其他片段
要使用选项卡从一个外部片段
切换到另一个(即:从水果切换到肉),我在外部片段
容器中执行片段事务:
private void switchFragment(Fragment fragment, String fragmentTag) {
final FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_outer, fragment, fragmentTag);
ft.commit();
}
问题是在切换第一级片段时,其子片段管理器的状态不会保持
例如,想象一下:
-我从FuitFragment开始
-创建时,水果片段会附加嵌套的水果列表片段
-用户在嵌套的Fragment
容器中从FruitListFragment导航到FruitDetailFragment
-用户切换到另一个选项卡
-用户切换回“水果”选项卡
-FuitFragment的子项“FragmentManager*”不会自动将FrootDetailFragment放入嵌套的片段容器中
更具体地说,当切换回外部片段时:
- 调用
onCreate
,其中savedInstance
==null
- 调用onCreateView
,并使用savedInstance
==null
因此,当调用外部片段onCreate
方法时,我无法判断是否要附加子片段
(就像人们通常对活动所做的那样)。
此外,如果我不附加它(使用实例变量检查我是否切换回它),子片段
容器将只是空的
实验和笔记
- 我已经试验过,如果在附加外部片段事务时将其添加到backbackback,在切换回它时,
onCreate
方法不会被调用,并且子FragmentManager
将记住并附加它以前拥有的片段。
但是,我无法按照将其添加到backbackback
- 将
setRetainInstance
设置为true不会产生任何效果
那么,我应该如何正确地恢复子项的状态FragmentManager
是我做错了什么,还是Android中围绕嵌套片段的所有内容都没有得到很好的支持(或者有点破损),我根本不应该使用嵌套片段提供导航?正如阿巴斯指出的,问题是我使用了替换
在片段之间切换
我已在活动中更改为代码,以放置外部片段,并且它可以工作:
private void showChildFragment(int itemId) {
final FragmentManager fragmentManager = getSupportFragmentManager();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
final Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_outer);
if (currentFragment != null) {
Log.v(TAG, "Detaching item #" + currentFragment);
currentFragment.setMenuVisibility(false);
currentFragment.setUserVisibleHint(false);
transaction.detach(currentFragment);
}
// Do we already have this fragment?
final String tag = makeFragmentTag(container.getId(), itemId);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
fragment = createFragmentForViewId(itemId);
Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
transaction.add(container.getId(), fragment, tag);
} else {
Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
transaction.attach(fragment);
}
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
transaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
private Fragment createFragmentForViewId(int itemId) {
switch (itemId) {
case FRAGMENT_ID_LIBRARY:
return LibraryNavigationFragment.createInstance();
case FRAGMENT_ID_FEED:
return WebAppFragment.createInstance("feed");
case FRAGMENT_ID_SUGGEST:
return WebAppFragment.createInstance("suggest");
default:
throw new IllegalArgumentException();
}
}
这段代码几乎是从android.support.v4.app.FragmentPagerAdapter
复制粘贴而来,就像ViewPagers
使用片段一样工作 使用getChildFragmentManager()它不会崩溃
private void switchFragment(Fragment fragment, String fragmentTag) {
final FragmentManager fm = getChildFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_outer, fragment, fragmentTag);
ft.commit();
}
一个简单的解决方案是根据需要将replace()
方法调用替换为add()
attach()
和remove()
和detach
detach()
method调用保留片段的状态,只对UI隐藏。没错,阿巴斯。我是在读《碎片密码》时得出这个结论的。我已经用有效的代码发布了答案,但是如果你想发布你的答案,我会将其标记为有效答案。你有完整的实现,你可以告诉我吗?我需要实现这一点。