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

Navigation 2.3.5 Activity重建时getGraph()报错及状态恢复失效问题

问题根因

这个异常是Navigation 2.3.5版本的典型场景问题,触发逻辑非常明确:

  • Activity被系统回收重建、或开启「不保留活动」选项时,super.onCreate()执行阶段不会自动完成NavController的导航图初始化,此时直接调用getGraph()就会抛出You must call setGraph() before calling getGraph()异常。
  • 你手动实现的状态保存恢复逻辑无效,核心原因是顺序错误:restoreState()仅能恢复回退栈状态,必须先执行setGraph()给NavController绑定导航图,才能调用restoreState()恢复栈数据,直接跳过setGraph步骤调用restoreState没有任何作用。
  • Navigation 2.2.0及以上版本已经内置了NavHostFragment的状态自动保存恢复逻辑,你手动在onSaveInstanceState里存nav_state的操作是多余的,反而可能和组件内置逻辑产生冲突。
修复步骤

按以下顺序调整代码即可解决:

  1. 移除你手动写的导航状态保存、恢复代码,包括onSaveInstanceState里的putBundle("nav_state")逻辑,以及onCreate里的restoreState()调用,交给组件自动处理即可。
  2. 调整NavController和ViewModel的初始化时机,必须保证在访问graph.id之前,NavController已经完成导航图绑定,参考代码如下:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 必须先加载布局,NavHostFragment是在布局inflate阶段完成绑定的
    setContentView(R.layout.activity_main)

    val navController = findNavController(R.id.nav_host_fragment)
    // 重建场景下先判断graph是否已初始化,未初始化则主动绑定导航图
    if (navController.currentDestination == null) {
        navController.setGraph(R.navigation.你的对应导航图ID)
    }

    // 此时graph已经完成初始化,再初始化作用域ViewModel不会报错
    val myViewModel: MyViewModel by navGraphViewModels(navController.graph.id) {
        defaultViewModelProviderFactory
    }
}
注意事项
  • 不要将navGraphViewModels的初始化写在Activity的成员变量赋值位置,成员变量初始化早于onCreate生命周期执行,此时NavController还未完成绑定,必然触发异常。
  • 如果项目存在多个导航图,不要在Activity层级统一初始化所有navGraph作用域的ViewModel,建议在对应导航图内的起始Fragment的onViewCreated生命周期里初始化对应作用域的ViewModel,此时NavController的导航图一定处于已初始化状态,不会出现时序问题。
  • 2.3.5版本不要在setContentView()调用之前执行findNavController(),此时拿到的NavController实例未完成和NavHostFragment的关联,所有graph相关操作都会失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:24:25