You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Navigation Drawer与Navigation Component实现应用重启后恢复上次打开的Fragment

实现方案选择结论

两种方案均可正常实现需求,优先选择「binding.navView.setNavigationItemSelectedListener设置选中监听 + 手动触发选中」的组合方案,比直接调用Navigation.findNavController().navigate()更稳妥:直接调用navigate()需要额外手动同步侧边栏菜单项的选中高亮状态,还要额外处理回退栈逻辑,很容易出现页面跳转正确但侧边栏选中状态不匹配、按返回键回到首页的问题。

完整实现步骤
  • 第一步:修正DataStore写入时机,保证所有页面切换场景都能正确存储上次访问的目的地
    不要只在侧边栏点击监听里存目的地ID,给NavController注册全局OnDestinationChangedListener,不管是侧边栏跳转、按钮跳转、通知跳转触发的页面切换都会触发监听,不会漏存:

    navController.addOnDestinationChangedListener { _, destination, _ ->
        // 存destination.id到DataStore,这个ID和导航图、侧边栏menu的item ID完全一致
        viewModel.saveLastDestinationId(destination.id)
    }
    
  • 第二步:应用重启时的恢复逻辑,放在MainActivityonCreate方法中,NavController初始化完成后执行
    注意DataStore是异步读写,用生命周期协程包裹读取逻辑,避免阻塞主线程,同时要校验读取到的ID合法性:

    lifecycleScope.launchWhenStarted {
        // 读取上次存的ID,传入默认值(导航图的起始页ID,第一次启动没有存储记录时用)
        val lastDestId = viewModel.getLastDestinationId(navController.graph.startDestinationId)
        // 校验ID是否在导航图中存在,避免存了无效ID导致崩溃
        if (navController.graph.contains(lastDestId)) {
            // 直接设置侧边栏选中项,自动触发你已配置的选中监听跳转,同时同步高亮状态
            binding.navView.setCheckedItem(lastDestId)
            // 如果你要选直接调用navigate的方案,记得配置NavOptions清理回退栈,避免按返回键回到首页
            /*
            navController.navigate(
                lastDestId,
                null,
                NavOptions.Builder()
                    .setPopUpTo(navController.graph.startDestinationId, true)
                    .build()
            )
            */
        }
    }
    
  • 第三步:前置校验要求
    导航图中每个Fragment的android:id必须和侧边栏menu对应item的android:id完全一致,这是Navigation组件原生适配侧边栏的基础要求,ID不匹配会导致跳转/选中失效。

常见DataStore不生效排查点
  • 存储时机不对,只在侧边栏点击时存,其他跳转场景没更新存储值
  • 恢复逻辑执行太早,NavController还没初始化完成就调用跳转
  • 协程作用域不对,读DataStore的协程被提前取消,没拿到存储值就执行了跳转逻辑

内容的提问来源于stack exchange,提问作者Dr Mido

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:48:02