android - 使用android架构组件时不应该销毁和创建的片段
问题描述
我有点傻。我有一个包含 3 个片段的游戏应用程序。片段 A、片段 B、片段 C 使用实时数据和来自 Google 的导航组件。当用户在片段 C 上完成时,我使用导航组件将返回堆栈弹回片段 A。
第一个问题:当我弹出回栈时,该片段的 onDestroy() 被调用。我的印象是,这不应该通过这篇文章发生:链接。
第二个问题:一旦用户被弹回片段A,有一个选项可以导航到片段B。一旦调用该行进行导航,片段C就会以某种方式添加到返回堆栈中,并创建视图,导致我的应用程序崩溃,因为我有一个侦听器在我的 viewModel 中侦听一个变量,该变量在片段 B 中设置的片段之间共享。
我不知道为什么当我弹出返回堆栈时片段会被破坏,我也不知道为什么当我尝试导航到片段 B 时它会被创建。
我已经记录了生命周期回调,以确保片段 C 被销毁并重新创建。而且我在单步执行应用程序时监控了导航组件的后台堆栈。看到看似随机添加的片段 C。
考虑到它是观察者内部的代码导致我的应用程序崩溃,我也尝试只在 onResume() 中添加观察者并在 onDestroy() 中分离它,但是,当重新创建片段时,它通过 onResume() 并刚刚附加立即观察者
从片段 A 导航到片段 B
viewModel.addPlayer(asPlayer).addOnCompleteListener {
Log.d("Game", "current destination before joining: "+resources.getResourceEntryName(navController.currentDestination!!.id))
navController.navigate(R.id.action_joinGameFragment_to_waitingFragment)
}
观察者被调用导致崩溃。
//so this observer is not getting detached, maybe manually detach it and reattach it in on resume
viewModel.gameExists.observe(this, androidx.lifecycle.Observer { exists ->
//someone ended the game
var debug = navController
if(!exists && navController.currentDestination?.id == R.id.gameFragment){ endGame() }
})
崩溃的函数
fun endGame(){
viewModel.endGame()
Log.d("Game", "current destination before crash: "+resources.getResourceEntryName(navController.currentDestination!!.id))
timer.cancel()
Log.d("Game", "current destination before poping: "+resources.getResourceEntryName(navController.currentDestination!!.id))
navController.popBackStack(R.id.startFragment, false)
Log.d("Game", "current destination after poping: "+resources.getResourceEntryName(navController.currentDestination!!.id))
}
日志猫的结果
2019-06-16 20:13:40.278 13021-13021/com.dangerfield.spyfall D/Game: current destination before poping: (FRAGMENT C)
2019-06-16 20:13:40.279 13021-13021/com.dangerfield.spyfall D/Game: current destination after poping: (FRAGMENT A)
2019-06-16 20:13:40.279 13021-13021/com.dangerfield.spyfall D/View Model: game = null
2019-06-16 20:13:40.299 13021-13021/com.dangerfield.spyfall D/GAME: ON DESTROY
2019-06-16 20:13:40.315 13021-13021/com.dangerfield.spyfall D/View Model: game = null
2019-06-16 20:14:05.289 13021-13021/com.dangerfield.spyfall D/Game: current destination before joining: (FRAGMENT A)
2019-06-16 20:14:05.316 13021-13021/com.dangerfield.spyfall D/Game: on Create
2019-06-16 20:14:05.317 13021-13021/com.dangerfield.spyfall D/Game: onCreateView
2019-06-16 20:14:05.353 13021-13021/com.dangerfield.spyfall D/GAME: ON RESUME
2019-06-16 20:14:05.353 13021-13021/com.dangerfield.spyfall D/Game: current destination before crash: (FRAGMENT C)
019-06-16 20:14:05.359 13021-13021/com.dangerfield.spyfall E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dangerfield.spyfall, PID: 13021
kotlin.UninitializedPropertyAccessException: lateinit property timer has not been initialized
at com.dangerfield.spyfall.game.GameFragment.endGame(GameFragment.kt:158)
(游戏片段为片段C)
任何帮助/方向将不胜感激,非常感谢。
解决方案
推荐阅读
- vue.js - Vue CLI 未安装
- mongodb - 致命错误 - Docker 桌面中的 MongoDB ReplicaSet 节点启动问题
- azure-functions - Azure Functions 配置 Key Vault 提供程序不起作用
- sql - 如何使用嵌套 CASE 语句检查 3 列中的值以设置 Microsoft SQL 中第 4 列中的值?
- python - 我可以只抓取没有特定属性的元素吗?
- python - 无法使用漂亮的汤和 python 抓取图像 URL
- r - 使用 specaccum() 外推物种累积曲线
- python - python函数标记数据帧中前30%的事务
- r - 具有 2 个捕获组的正则表达式,“key=value”或“value_only”
- java - 当读取和写入请求来自同一段时,ConcurrentHashMap 如何工作?