Я объявил абстрактную модель представления (скажем, AnimalsViewModel
), две модели представления расширяют ее (DogViewModel
, CatViewModel
).
соответствующие фрагменты (DogFragment
, CatFragment
) содержат общий фрагмент (AnimalFragment
), которому нужен экземпляр того, что AnimalViewModel
использует родительский фрагмент.
Но как мне это получить AnimalFragment
? Я попробовал это:
class AnimalFragment : Fragment() {
private val viewModel by lazy {
requireParentFragment().getViewModel<AnimalViewModel>()
}
}
но это не работает, поскольку koin не находит экземпляр, принадлежащий родителю, и выдает ошибку, сообщающую, что он не находит поставщика для AnimalViewModel
(очевидно, поскольку он абстрактный). Я пытался сделать это интерфейсом, но безрезультатно.
Есть ли способ добиться этого?
Обновлено:
чтобы внести ясность, скажем, DogFragment
имеет экземпляр DogViewModel
с идентификатором 1 и CatFragment
имеет CatViewModel
с идентификатором 2, AnimalFragment
внутри внутри DogFragment
должен получить viewModel #1, а тот, что внутри CatFragment
, должен получить #2.
Проблема не в том, чтобы получить viewModel в правильной области, а в том, чтобы получить viewModel с использованием абстрактного класса в качестве идентификатора.
это работает отлично, но я не хочу добавлять параметр в AnimalFragment
, чтобы знать, какую модель представления он должен запрашивать
private val viewModel by lazy {
requireParentFragment().getViewModel<DogViewModel>()
}
Я также видел by viewModels(ownerProducer = { requireParentFragment() })
использованный
@tyczj Я не думаю, что это проблема. AnimalFragment правильно запрашивает у своего родителя экземпляр viewModel, но не может его найти, поскольку я запрашиваю абстрактный класс. Если я укажу реализацию, которую хочу, она будет работать правильно
В итоге я определил интерфейс, который предоставляет модель представления требуемого абстрактного типа. Это не идеально, но лучше, чем передавать аргументы или упоминать родительские фрагменты в дочернем элементе.
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()}")
}
}
попробуйте сделать
requireParentFragment().requireParentFragment()
, как предложено здесь stackoverflow.com/questions/60356505/… и здесь medium.com/@kennethchangla/…