我有一个带有抽屉布局模板的应用程序。滑入式菜单中的可选片段之一具有框架布局。在框架布局中选择这个片段首先会弹出一个片段,其中列出了实体。选择实体后,片段将切换到具有编辑视图的片段。
所以层次结构是这样的:
MainActivity --> ?NavHostFragment? --> ManageEntitiesFragment --> ListEntitiesFragment || 编辑实体片段
我使用 viewmodel 的 livedata 的观察者处理子片段切换,如下所示:
管理实体片段:
private FrameLayout mFrame;
private FragmentTransaction mTransaction;
private MyViewModel mViewModel;
...
mViewModel.getFragment().observe(getViewLifecycleOwner(), new Observer<Fragment>() {
@Override
public void onChanged(Fragment fragment) {
mTransaction = getChildFragmentManager().beginTransaction();
mTransaction.replace(mFrame.getId(), fragment).addToBackStack(fragment.getTag());
mTransaction.commit();
}
});
到目前为止,这在向前和向后导航方面效果很好。但是如果我在按下后退按钮的情况下从子片段向后退,则视图模型不会改变,所以如果我例如旋转屏幕,子片段就会弹出。我试图在分离子片段时设置父视图模型的属性:
编辑实体片段:
@Override
public void onDetach() {
mParentFragment.InitFragment(); //sets the viewmodel's fragment to the starting (list) fragment
super.onDetach();
}
但是这样每次子片段分离时它都会运行。这意味着,当子片段处于活动状态时旋转屏幕,这也会初始化框架布局。
我试图设置一个 bool 变量来检查分离是否来自实例保存,但它没有成功并且对此感到奇怪。
并尝试了这个:
主要活动:
@Override
public void onBackPressed() {
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
boolean handled = false;
for (Fragment f : fragmentList) {
if (f instanceof FragmentWithCustomEvents) { //EditEntityFragment is a type of this class
handled = ((FragmentWithCustomEvents) f).onBackPressed();
if (handled) {
break;
}
}
}
if (!handled) {
super.onBackPressed();
}
}
在这种情况下 getSupportFragmentManager().getFragments() 不会获得子片段,只有 NavHostFragment。为了让它工作,我应该这样做:
List<Fragment> fragmentList = getSupportFragmentManager()
.getFragments().get(0)
.getChildFragmentManager()
.getFragments().get(0)
.getChildFragmentManager().getFragments();
这似乎也很奇怪……
所以我的问题是我应该如何处理它的子片段之间的嵌套片段中的向后导航?如何在片段中处理 ,,onbackstacking'' ?有没有办法在将片段推回堆栈时销毁片段?也许我的架构错了?