重启Activity调用navController.setGraph抛出NullPointerException问题求助
问题分析与解决方案
问题原因
当通过finish()+startActivity(intent)重启Activity时,系统会保留原Activity的部分状态(包括NavController内部的导航状态)。此时如果复用之前的NavGraph实例调用setGraph,NavController在恢复旧状态的过程中,原本应为非空Int类型的参数(如目标页面ID)可能因状态恢复异常变为null,触发Kotlin非空类型转换失败,抛出NullPointerException: null cannot be cast to non-null type kotlin.Int。
另外,复用旧的NavGraph实例会导致状态污染——重启前的NavGraph已绑定旧NavController或保存了无效状态,再次传入新的NavController时会引发类型错误。
可行解决方案
1. 每次创建新的NavGraph实例
不要复用已存在的NavGraph,而是每次从资源重新加载,确保实例状态干净:
private fun openLogin(navigateToChatAutomatically: Boolean) { // 从导航资源重新加载全新的NavGraph实例 val navGraph = navInflater.inflate(R.navigation.main_nav_graph) navGraph.setStartDestination(R.id.login_nav_graph) navController.setGraph( navGraph, bundleOf( "pageCount" to 3, "navigateToChatAutomatically" to navigateToChatAutomatically ) ) }
2. 优化Activity重启逻辑,清除旧状态
重启时添加清除任务栈的标志,确保新启动的Activity是完全全新的实例,不会携带旧状态:
fun FragmentActivity.restart() { val intent = this.intent // 清除任务栈,避免恢复旧Activity的状态数据 intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK finish() startActivity(intent) }
3. 仅在Activity首次创建时设置导航图
利用savedInstanceState判断是否为首次创建,重建时依赖系统自动恢复导航状态,避免重复设置:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) // 仅首次创建Activity时设置导航图 if (savedInstanceState == null) { setupNavGraph(navController) } } private fun setupNavGraph(navController: NavController) { val isLoggedIn = // 替换为你的登录状态判断逻辑 val navGraph = navInflater.inflate(R.navigation.main_nav_graph) navGraph.setStartDestination(if (isLoggedIn) R.id.home_fragment else R.id.login_nav_graph) navController.setGraph( navGraph, bundleOf("navigateToChatAutomatically" to false) ) }
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

