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

Hilt使用hiltNavGraphViewModels遇重启导航栈异常求助

解决hiltNavGraphViewModels在应用终止重启后导航栈丢失的报错问题

问题背景

原本使用viewModels()委托无法创建跨Fragment的SharedViewModel,切换为hiltNavGraphViewModels()后实例创建问题解决,但通过Logcat的「Terminate App」操作强制终止应用后重启,抛出异常:

No destination with ID 2131296453 is on the NavController's back stack. The current destination is null

核心原因

hiltNavGraphViewModels()是绑定到指定导航图(NavGraph)的ViewModel委托,它要求NavController的回退栈中存在对应导航图的目的地。当应用被强制终止后,系统默认不会自动恢复导航栈状态,重启时NavController的回退栈为空,找不到绑定的导航图ID,因此触发报错。

解决方案

1. 启用导航栈的自动状态恢复

在配置NavHostFragment时开启状态恢复开关,让系统自动保存和恢复导航栈状态:

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
        // 启用导航状态自动恢复
        navHostFragment.restoreStateEnabled = true
        navController = navHostFragment.navController
    }
}

2. 手动保存/恢复导航栈状态

如果系统自动恢复失效(比如进程被完全销毁),可以手动在Activity的生命周期中保存和恢复导航栈状态:

class MainActivity : AppCompatActivity() {
    private lateinit var navController: NavController
    private val NAV_STATE_KEY = "nav_controller_state"

    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

        // 从savedInstanceState恢复导航栈状态
        savedInstanceState?.getBundle(NAV_STATE_KEY)?.let {
            navController.restoreState(it)
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        // 保存当前导航栈状态
        outState.putBundle(NAV_STATE_KEY, navController.saveState())
    }
}

3. 安全获取ViewModel(避免空状态报错)

在Fragment中先校验NavController的状态,确保导航图存在后再获取ViewModel,避免直接调用hiltNavGraphViewModels()导致崩溃:

class TargetFragment : Fragment() {
    // 替换为你的导航图ID
    private val NAV_GRAPH_ID = R.id.your_shared_nav_graph

    // 延迟初始化ViewModel,确保导航栈状态正常
    private val sharedViewModel: SharedViewModel by lazy {
        val navController = findNavController()
        // 检查导航栈中是否存在目标导航图的目的地
        val hasValidNavGraph = navController.backStack.any { it.destination.id == NAV_GRAPH_ID }
        if (navController.currentDestination != null && hasValidNavGraph) {
            hiltNavGraphViewModels<NAV_GRAPH_ID>()
        } else {
            // 导航栈丢失时的降级处理,比如用当前Fragment的ViewModelProvider创建实例
            ViewModelProvider(this)[SharedViewModel::class.java]
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 确保NavController就绪后再使用ViewModel
        findNavController().currentDestination?.let {
            sharedViewModel.someLiveData.observe(viewLifecycleOwner) { data ->
                // 业务逻辑处理
            }
        }
    }
}

4. 检查依赖兼容性

确保Navigation和Hilt的版本匹配,避免版本冲突导致的状态恢复异常:

// 导航组件(建议使用稳定版)
implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
implementation "androidx.navigation:navigation-ui-ktx:2.7.7"

// Hilt相关依赖
implementation "com.google.dagger:hilt-android:2.48"
kapt "com.google.dagger:hilt-android-compiler:2.48"
implementation "androidx.hilt:hilt-navigation-fragment:1.1.0"

注意事项

  • 确认hiltNavGraphViewModels()指定的ID是导航图(NavGraph)的ID,而非单个目的地(Destination)的ID;
  • 如果Activity使用了特殊启动模式(如singleInstance),可能会干扰导航栈恢复,需检查启动模式配置;
  • 对于需要持久化的ViewModel数据,建议将数据保存到本地存储(如Room、SharedPreferences),避免依赖导航栈状态恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:25:41