I've declared an abstract viewModel (let's say AnimalsViewModel
), two viewModels extend it (DogViewModel
, CatViewModel
)
the corresponding fragments (DogFragment
, CatFragment
) host a common fragment (AnimalFragment
) that needs the instance of whatever AnimalViewModel
the parent fragment is using.
But how can I get it in AnimalFragment
? I tried this:
class AnimalFragment : Fragment() {
private val viewModel by lazy {
requireParentFragment().getViewModel<AnimalViewModel>()
}
}
but it doesn't work as koin doesn't find the instance owned by the parent and throws an error stating that it doesn't find a provider for AnimalViewModel
(obviously, since is abstract). I tried to make it an interface to no avail.
Is there any way to achieve this?
EDIT:
to clarify, let's say DogFragment
has an instance of DogViewModel
with id 1 and CatFragment
has CatViewModel
with id 2, AnimalFragment
inside inside DogFragment
should receive viewModel #1 and the one inside CatFragment
should receive #2.
The problem is not getting the viewModel in the correct scope but getting the viewModel using an abstract class as identifier.
this works perfectly but I don't want to add a parameter to AnimalFragment
to know which viewModel it should request
private val viewModel by lazy {
requireParentFragment().getViewModel<DogViewModel>()
}
I ended up defining an interface which provides a viewmodel of the required abstract type. It's not ideal but it's better than passing arguments around or mentioning the parent fragments in the child.
interface AnimalContainer {
abstract val viewModel: AnimalViewModel
}
class AnimalFragment : Fragment() {
private val viewModel by lazy {
(requireParentFragment() as? AnimalContainer)?.viewModel
?: error("AnimalFragment not allowed in container ${requireParentFragment()}")
}
}