android - 为什么导航返回后会创建一个新的 ViewModel 实例?
问题描述
我目前正在开发基于MVVM的 Android 应用程序,因此我使用ViewModel原理来包含我的 UI 数据。
我也知道ViewModel链接到它的所有者,并且当所有者被销毁时它被销毁。(https://developer.android.com/topic/libraries/architecture/viewmodel)。
我的问题发生在片段 A 和 B 之间(在上图中可见)。
我的 Fragment A 包含一个 recyclerview,当我单击该元素时,它会使用组件导航将我定向到 Fragment B(参见下面的示例)。
view?.findNavController()?.navigate(R.id.action_commandListFragment_to_commandDetailsFragment)
我的片段 B 使用 ViewModelProvider 初始化“CommandDetailViewModel”,其子片段(C & D)通过将“requireParentFragment()”作为 ViewModelProvider 的参数传递来检索它。
//Fragment B
mviewModel = ViewModelProvider(this).get(CommandDetailsViewModel::class.java)
//Fragment C & D
mparentViewModel = ViewModelProvider(requireParentFragment()).get(CommandDetailsViewModel::class.java)
如果我单击片段 D 上的按钮,我会返回片段 A,始终使用控制器导航。
//In Fragment B
mviewModel.mCurrentCommandFinished.observe(viewLifecycleOwner, Observer {
if(it){
view?.findNavController()?.navigate(R.id.action_commandDetailsFragment_to_commandListFragment)
}
})
到目前为止,我明白了,但我意识到我做错了,确实,返回片段 A 这样做是因为 ViewModel 的布尔 LiveData 更改为“true”,因此即使在导航之后也保留为“true”。
当我单击第 1 项时,我预计会遇到问题,变量为 true 我会立即被放回我的列表中,但事实并非如此,创建了一个新的 ViewModel,因此将值设置为 false(默认一)我不明白为什么。
导航是否具有完全破坏片段 B 以及关联的 viewModel 的效果?
因为我不明白为什么每次单击我的元素时都会创建一个新的 viewModel 实例,而我的子片段设法获取先前创建的实例。
注意: viewModel 的影响是在片段 B、C 和 D 中的“onActivityCreated(savedInstanceState: Bundle?)”中完成的。
编辑:我试图在片段 B 的覆盖“onDestroy()”函数中添加一个日志,我发现片段没有被破坏,他的 VM 也没有。
问题是我重新创建了我的片段的一个新实例
view?.findNavController()?.navigate(R.id.action_commandListFragment_to_commandDetailsFragment)
有没有办法检索“原始”实例或销毁它?
编辑2:这是我的错,我没有利用从片段B到片段A的动作中的“popUpTo”和“popUpToInclusive”变量,所以我的片段B仍在堆栈中但不再使用,现在它被正确销毁(https://developer.android.com/guide/navigation/navigation-navigate)
解决方案
推荐阅读
- php - 尝试在 php 中进行密码验证时出现错误“尝试访问 bool 类型值的数组偏移量...”
- json - 使用 Play Json 序列化多态 F 案例类
- mysql - MySQL 从具有名称 (AS) 的字段中访问数据
- twilio - Twilio A2P 10DLC 迁移
- c++ - 返回具有新数组成员的结构时堆地址错误
- .htaccess - 我们如何在 .htaccess 文件中实现以下场景的 301 重定向
- python-3.x - RabbitMQ “消息已发布,但未路由。” 直接到扇出交换绑定
- javascript - Oracledb(NodeJS)在我每次创建一个新池时工作,但并非没有。需要它使用已经创建的池
- javascript - 如何使图像不透明度响应光标位置
- dynamic - 将动态整数转换为十六进制颜色代码