简体   繁体   English

使用导航组件在父片段的 scope 中共享 ViewModel

[英]Shared ViewModel in scope of parent fragment using Navigation Component

I am trying to use the same instance of ViewModel in Parent Fragment and its children, using Navigation Component.我正在尝试使用导航组件在父片段及其子片段中使用相同的 ViewModel 实例。 The hierarchy is as follows: Single Activity that has navigationHost.层次结构如下:具有导航主机的单个活动。 This host has 3 child fragments, A, B and C. The last fragment has also navigationHost with 2 fragments: X and Y. The below graph illustrates the hierarchy.该主机有 3 个子片段,A、B 和 C。最后一个片段也有带有 2 个片段的导航主机:X 和 Y。下图说明了层次结构。

片段层次结构

Expected: I would like to share the same instance of fragment C ViewModel with fragment X and Y.预期:我想与片段 X 和 Y 共享片段 C ViewModel 的相同实例。

Current: The ViewModel of fragment C is initialized twice: Once when fragment C is initialized and second time when fragment X is initialized.当前:片段 C 的 ViewModel 被初始化两次:一次是片段 C 被初始化,第二次是片段 X 被初始化。 The Fragment X is set as a default destination in the fragment C nav graph.片段 X 在片段 C 导航图中设置为默认目的地。 When I am changing the default destination to Y, the ViewModel is initialized in C and Y.当我将默认目标更改为 Y 时,ViewModel 在 C 和 Y 中初始化。

What I tried already: In child viewModels I use this:我已经尝试过的:在子视图模型中我使用这个:

        val viewModel: ParentViewModel =
        ViewModelProvider(findNavController().getViewModelStoreOwner(R.id.parent_graph)).get(
            ParentViewModel::class.java
        )

In parent viewModel I use this:在父 viewModel 中我使用这个:

    val viewModel by viewModels<ParentViewModel>()

I've also tried to inject the viewModel using Koin sharedViewModel with scope of fragment:我还尝试使用带有 scope 片段的 Koin sharedViewModel 注入 viewModel:

val viewModel by sharedViewModel<ParentViewModel>(from = { parentFragment!! })

Also no luck.也没有运气。

Is it possible or maybe it is a bug in navigation library?有可能还是导航库中的错误?

A NavHostFragment is a fragment itself, so your structure is actually NavHostFragment本身就是一个片段,所以你的结构实际上是

Fragment C -> NavHostFragment -> Fragment X
                              -> Fragment Y

Ie, the parentFragment you get from Fragment X is not Fragment C - it is the NavHostFragment you added in between the two.即,您从 Fragment X 获得的parentFragment不是Fragment C - 它是您在两者之间添加的NavHostFragment

Therefore if you want to get a ViewModel from Fragment C, you'd need to use requireParentFragment().requireParentFragment() - the parent of your NavHostFragment is Fragment C.因此,如果您想从片段 C 获取ViewModel ,则需要使用requireParentFragment().requireParentFragment()的父NavHostFragment是片段 C。

Cannot find a parameter with this name: from ------------update----------------找不到具有此名称的参数:来自 ----------update----------------

for those facing the same issue, check here koin issue discuss about, and maybe here might be helpful.对于那些面临相同问题的人,请查看此处的 koin 问题讨论,也许这里可能会有所帮助。

I'm using我在用着

//child fragment    
    private val viewModel: TripParentViewModel by viewModel(owner = { ViewModelOwner.Companion.from(requireParentFragment().requireParentFragment().viewModelStore)})

//parent fragment
private val parentViewModel by viewModel<TripParentViewModel>()

as solution,作为解决方案,

class TripParentViewModel:ViewModel() {

    var count = 0
    fun test(){
        when(count){
            0 -> Timber.d("first click")
            1 -> Timber.d("second click")
            2 -> Timber.d("third click")
        }
        Timber.d(count.toString())
        count++
    }
}

currently, I run this when change fragment, I didn't see any problem so far, if anything goes wrong, I will update here目前,我在更改片段时运行它,到目前为止我没有看到任何问题,如果有任何问题,我会在这里更新

  • koin_version = "2.2.1" koin_version = "2.2.1"
  • navigation_version = "2.3.5" navigation_version = "2.3.5"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM