Reputation: 355
I am trying to use the same instance of ViewModel in Parent Fragment and its children, using Navigation Component. 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.
Expected: I would like to share the same instance of fragment C ViewModel with fragment X and Y.
Current: The ViewModel of fragment C is initialized twice: Once when fragment C is initialized and second time when fragment X is initialized. The Fragment X is set as a default destination in the fragment C nav graph. When I am changing the default destination to Y, the ViewModel is initialized in C and 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:
val viewModel by viewModels<ParentViewModel>()
I've also tried to inject the viewModel using Koin sharedViewModel with scope of fragment:
val viewModel by sharedViewModel<ParentViewModel>(from = { parentFragment!! })
Also no luck.
Is it possible or maybe it is a bug in navigation library?
Upvotes: 10
Views: 6869
Reputation: 61
Cannot find a parameter with this name: from ------------update----------------
for those facing the same issue, check here koin issue discuss about, and maybe here might be helpful.
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
Upvotes: 1
Reputation: 199795
A NavHostFragment
is a fragment itself, so your structure is actually
Fragment C -> NavHostFragment -> Fragment X
-> Fragment Y
I.e., the parentFragment
you get from Fragment X is not Fragment C - it is the NavHostFragment
you added in between the two.
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.
Upvotes: 18