che*_*e10 5 android android-fragments android-navigation android-viewmodel android-architecture-navigation
谷歌表示,在 Fragment 之间进行通信时,通过将其范围限定为 Activity 来使用 SharedViewModel。
在单个 Activity 应用程序中,这意味着该 Activity 将散布着可能不再需要的 ViewModel,并且它们将在整个生命周期中保留在那里。考虑一些示例,例如扩展的注册流程或考虑几个屏幕的示例。
推荐的一种方法是使用父片段作为范围,但这只有在存在父片段时才可能。它可以只是不同的片段。
我想出了以下解决方案,我想知道它有多可行或有多糟糕,是否有更好的方法?
考虑到我有两个名为ExampleOneFragmentand的片段ExampleTwoFragment,为了简单起见,我希望它们具有共享范围,而不实际将其范围限定到活动。假设我想更新其中的文本视图ExampleOneFragment,ExampleTwoFragment因此我为两者创建一个像这样的 SharedViewModel
因为ExampleOneFragment它将是:
private val mSharedViewModel by lazy {
ViewModelProvider(this).get(SharedViewModel::class.java)
}
Run Code Online (Sandbox Code Playgroud)
因为ExampleTwoFragment我想出了这个:
private val mSharedViewModel by lazy {
ViewModelProvider(supportFragmentManager().findFragmentByTag(ExampleOneFragment.TAG) ?: this).get(SharedViewModel::class.java)
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但我不知道这会导致什么样的问题。
我发现了一些其他解决方案:根据@mikhehc这里,我们实际上可以创建我们自己的 ViewModelStore。这将使我们能够精细地控制 ViewModel 必须存在的范围。但我不明白如何让它适用于片段?
其次,仍然是将其范围限定为活动的黑客方法,但使用我在此处找到的相同密钥通过虚拟视图模型将其清除
谁能指导我什么是正确的方法?我无法转向 NavGraphs,因为它是一个已经启动并正在运行的项目,并且确定活动范围感觉是错误的。谢谢。
这似乎有效,但我不知道这会导致什么样的问题。
此代码仅在以下情况下才有效:
ExampleOneFragment始终首先被创建FragmentManager的相同内容中ExampleTwoFragmentExampleOneFragment.TAG如果这些假设中的任何一个失败,您将得到单独的视图模型实例,因为supportFragmentManager().findFragmentByTag(ExampleOneFragment.TAG) ?: this将解析为this.
但我不明白如何让它适用于片段?
您可以按照该答案中显示的方式使用它,或者通过任何其他接受ViewModelStoreOwner. 在这一行中:
val viewModel = ViewModelProvider(myApp, viewModelFactory).get(CustomViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)
myApp你会从你的Fragmentas得到:
val myApp = requireContext().application as MyApp
Run Code Online (Sandbox Code Playgroud)
就我个人而言,我认为你指出的解决方案风险很大。生命ViewModelStore周期贯穿进程的整个生命周期,并且永远不会被清除。您最终将在所有内容中共享您的视图模型,并且该视图模型完成的所有操作都会被泄漏。创建自定义的概念ViewModelStoreOwner很好,但您应该做一些事情将该所有者的范围与其存储的视图模型的相关生命周期联系起来。答案试图在最后一段中围绕这一点跳舞;太多的开发人员会忽视这一点并遇到问题。
推荐的一种方法是使用父片段作为范围,但这只有在存在父片段时才可能。它可以只是不同的片段。
ViewModelStoreOwner那么,您的应用程序并不是以“开箱即用”的方式编写自动管理的。
最后,您正在寻找ViewModelStoreOwner在这两个片段之间共享的一个。在您的第一个解决方案中,您试图通过使用ViewModelStoreOwner其中一个片段来破解它,只有当您能够可靠地选择哪个片段时,这才有效。在您在其他答案中指出的解决方案中,您试图通过故意泄漏ViewModelStoreOwner.
根据您的具体情况,您可能可以考虑其他方法。例如,您的依赖倒置框架(Dagger/Hilt、Koin 等)可能有一些选项来装配绑定ViewModelStoreOwner到特定一对片段实例的 。
| 归档时间: |
|
| 查看次数: |
1180 次 |
| 最近记录: |