页面3个Tab,分别为A
,B
,C
A
页面�内有 ViewPager2,内部有多个子页面D,其余无子 Fragment
依赖项
implementation("androidx.navigation:navigation-fragment:2.4.2")
implementation("androidx.appcompat:appcompat:1.4.1")
implementation("com.google.android.material:material:1.5.0")
页面布局
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/main_nav"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/main_nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_fg_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/main_nav_menu" />
</LinearLayout>
1. 使用默认设置,不做任何处理
mBinding.bottomNavFgMain.setOnItemSelectedListener(item -> {
// 这里我将 menu 的 id 与 NavDestination 的 id 一致对应
findNavController().navigate(item.getItemId());
return true;
});
测试过程 | 结果 |
---|---|
APP 启动 | A,D初始化 state == null; state == null |
切到B | B初始化 state == null; A,D到 onDestroyView |
切到C | C初始化 state == null; B 到 onDestroyView |
切到B | B1初始化 state == null; C 到 onDestroyView |
切到A | A1,D1 初始化 state == null; B1 到 onDestroyView |
多次按返回键 | A1->B1->C->B->A->桌面 |
其中A1,B1表示每次跳转到的新页面 hashCode 打印出来都是不同的,意味着其实每次都是新建页面,栈内的对象实例一直在增加。返回键只是将这些栈内的实例重新显示。
state 表示
saveInstanceState
使用 NavigationUI
添加依赖
implementation("androidx.navigation:navigation-ui:2.4.2")
删除之前的跳转逻辑,使用
NavigationUI.setupWithNavController(mBinding.bottomNavFgMain, findNavController());
测试过程 | 结果 |
---|---|
APP 启动 | A,D初始化 state == null |
切到B | B初始化 state == null; A,D到 onDestroyView |
切到C | C初始化 state == null; B 到 onDestroy |
切到B | B1初始化 state != null; C 到 onDestroy |
切到A | A,D 初始化 state == null; B1 到 onDestroy |
切到B | B2初始化 state != null; A,D到 onDestroyView |
切到C | C1初始化 state == null; B2 到 onDestroy |
多次按返回键 | C1->A->桌面 |
其中B1、C1表示每次跳转到的新页面 hashCode 打印出来都是不同的。
总结
- 不做任何操作的话,Navigation 是单任务栈管理模式,只能往里填充和显示最近实例;
-
NavigationUI#setupWithNavController
则是通过配合popUpTo
及saveState
等API,保证只缓存默认导航页面A,其余同级界面离开前会保存状态,不会保留实例。 - 两者都会重建 UI,无法保存滚动位置等等...至于新版本多任务栈的特性,与避免 UI 创建完全不相干,如果欣赏 YouTube 那种风格的话,可以尝试。
总之,我个人认为 Navigation 不适合用作传统 APP 多 Tab 切换的主页,用作二级菜单确实不错。
网友评论