如何通过Navigation组件保存BottomNavigationView的Fragment实例
前置依赖要求
首先确保项目引入的Navigation组件版本≥2.5.0,配套Fragment依赖版本≥1.5.0,在模块级build.gradle中添加/升级对应依赖:
dependencies { // Fragment依赖,需匹配Navigation版本要求 implementation "androidx.fragment:fragment-ktx:1.5.0+" // Navigation组件依赖,版本不低于2.5.0即可,建议使用当前最新稳定版 implementation "androidx.navigation:navigation-fragment-ktx:2.7.7" implementation "androidx.navigation:navigation-ui-ktx:2.7.7" }
导航图配置规则
导航图res/navigation/nav_main.xml需要遵循以下规则:
- 根导航图的起始目的地必须是BottomNavigationView对应的一级Fragment之一
- 所有底部菜单项对应的一级Fragment,必须直接作为根导航图的直接子节点,不要嵌套在其他导航图下
- 不要给一级Fragment配置
popUpTo清空栈、launchDocument等特殊启动属性
配置示例:
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_main" app:startDestination="@id/homeFragment"> <!-- 底部菜单对应的一级Fragment,直接挂载在根导航图下 --> <fragment android:id="@+id/homeFragment" android:name="com.yourapp.HomeFragment" android:label="首页" /> <fragment android:id="@+id/dashboardFragment" android:name="com.yourapp.DashboardFragment" android:label="数据面板" /> <fragment android:id="@+id/profileFragment" android:name="com.yourapp.ProfileFragment" android:label="个人中心" /> <!-- 二级跳转页面正常配置即可,不影响一级页状态留存 --> <fragment android:id="@+id/settingsFragment" android:name="com.yourapp.SettingsFragment" android:label="设置" /> </navigation>
Activity绑定逻辑
不要手动实现BottomNavigationView的菜单项选中监听做跳转,直接使用官方提供的setupWithNavController扩展方法完成绑定,代码示例:
class MainActivity : AppCompatActivity() { private lateinit var navController: NavController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment navController = navHostFragment.navController // 调用官方扩展方法完成绑定,内部已实现多Tab栈管理与状态保存逻辑 findViewById<BottomNavigationView>(R.id.bottom_nav).setupWithNavController(navController) } override fun onSupportNavigateUp(): Boolean { return navController.navigateUp() || super.onSupportNavigateUp() } }
如果有自定义菜单选中逻辑的需求,不要直接调用navController.navigate()跳转,必须使用NavigationUI.onNavDestinationSelected()处理选中事件,否则会触发Fragment重复创建:
bottomNav.setOnItemSelectedListener { menuItem -> // 调用官方封装的选中处理逻辑,保留状态保存能力 NavigationUI.onNavDestinationSelected(menuItem, navController) }
常见避坑点
- 不要手动给底部Tab跳转加
popUpTo、singleTop等NavOptions配置,官方绑定方法内部已经做了适配 - 不要自定义NavHostFragment的FragmentFactory重写一级Fragment的创建逻辑,除非自行实现实例缓存
- 不要给NavHostFragment设置
app:defaultNavHost="false"属性,会破坏返回栈与状态管理逻辑
配置完成后验证:首次进入每个Tab会正常走Fragment创建生命周期,后续切换Tab时不会重新调用onCreate、onViewCreated方法,列表滚动位置、输入框内容等页面状态会自动留存。
内容的提问来源于stack exchange,提问作者pa1pal
相关产品推荐
相关产品推荐

