Jetpack Navigation 使用技巧
记录使用 Jetpack Navigation 的小技巧和注意事项
多导航布局切换
private val isHomeA = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_navigation)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
if (isHomeA) {
navHostFragment.navController.setGraph(R.navigation.my_simple_navigation)
} else {
navHostFragment.navController.setGraph(R.navigation.my_simple_navigation2)
}
}
- 布局 fragment_container 无
navGraph
,否则首页fragment
会多一次创建销毁 - 不可使用
Navigation.findNavController(this, viewId)
查找navController
来设置导航布局
出栈导航
navigation
布局内的fragment
标签的action
标签增加launchSingleTop
和popUpToInclusive
为true
,popUpTo
标签设置为当前fragment ID
,跳转时会把当前fragment
出栈,这样每次跳转后,Fragment
的返回栈内只有当前Fragment
。
<fragment
android:id="@+id/fragmentA"
android:name="com.example.myjetpackdemo.navigation.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a">
<action
android:id="@+id/action_fragmentA_to_fragmentB"
app:destination="@id/fragmentB"
app:launchSingleTop="true"
app:popUpTo="@id/fragmentA"
app:popUpToInclusive="true" />
</fragment>
- 跳转布局时请使用此 action ID,而不是使用 fragment ID
findNavController().navigate(R.id.action_fragmentA_to_fragmentB)
首页导航
navigation
布局内的fragment
标签的action
标签增加launchSingleTop
为true
,popUpTo
标签设置为首页 fragment ID,不设置popUpToInclusive
或设置为false
,跳转时会只保留首页在栈内
<fragment
android:id="@+id/fragmentA"
android:name="com.example.myjetpackdemo.navigation.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a">
<action
android:id="@+id/action_fragmentA_to_fragmentB"
app:destination="@id/fragmentB"
app:launchSingleTop="true"
app:popUpTo="@id/fragmentA" />
</fragment>
导航跳转 Activity
Navigation 可以通过设置 action 跳转 Activity,但需要注意 Activity 的生命周期,即设置 launchMode="singleTop"
时,来回跳转会重复创建 Activity 实例。
如果设置 Activity 的启动模式 launchMode="singleTask"
,会复用 Activity。但需要注意,不要全部使用 出栈导航。如果全部使用 出栈导航,使用 action 跳转其他 Activity 时,当前导航 Activity 内的最后一个 Fragment 并不会销毁,但会退出 NavController 的返回栈。产生的效果就是,下一次再进入此导航 Activity 时,可以看见跳出时的界面,但从此界面跳转,会报 IllegalArgumentException
无法找到当前 Fragment。
从这个现象也可以看出,Navigation 导航时,Fragment 有多份多地保存,出栈导航 无法清除 Activity 内所有的 Fragment,至少会保留一个 Fragment 进行显示,但时 NavController 管理的返回栈会清空,而造成异常。在文章《Bundle 工具解决 TransactionTooLargeException》中分析 Bundle 数据时也可以发现, Fragment 的 argument 参数也有多份保存。