使用navigate()方法跳转其他Fragment,再navigateUp()该Fragment出栈并返回上一个界面时,会重走上一个界面的onCreateView和onViewCreated()生命周期方法,导致View和数据的初始化代码逻辑会重新执行,每次返回都会刷新页面。并且如果上一页面中初始化逻辑较多,可能会导致返回时有明显卡顿。
问题场景:在项目中fragmentA界面的数据初始化操作是放在懒加载方法中执行,再跳转fragmentB界面并返回时,Afragment界面onViewCreated会重新执行View会重新初始化,但数据初始化只在懒加载方法中执行一次,这时上一fragment界面就会出现空白的情况。同时我在官方给出的Sunflower Demo中也验证了,同样是返回时上一fragment页面会重走。
问题原因:Navigation组跳转另一Fragment时,navigate()方法源码中使用的是ft.replace()方式,并不是add() hide() show(),这也导致了fragmentB覆盖fragmentA,返回时fragmentA是重新Create的。
public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args,
@Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
// ...省略
ft.replace(mContainerId, frag);
ft.setPrimaryNavigationFragment(frag);
// ...省略
}
解决方法:将NavHostFragment、FragmentNavigator类拷贝到项目中,修改FragmentNavigator中的navitgate()方法,并修改NavHostFragment中import FragmentNavigator的路径。
public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args,
@Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
// ...省略
if(mFragmentManager.getFragments().size()>0){
ft.hide(mFragmentManager.getFragments().get(mFragmentManager.getFragments().size()-1));
ft.add(mContainerId, frag);
}else {
ft.replace(mContainerId, frag);
}
// ft.replace(mContainerId, frag);
ft.setPrimaryNavigationFragment(frag);
// ...省略
}
同时在设置NavHost时与使用NavHostFragment.findNavController(this).navigate(actionId, args)方法跳转时,导包使用项目中的NavHostFragment。