Я работаю над Android, но я думаю, что концепция будет одинаковой на всех платформах.
У меня есть фрагмент A, содержащий другой фрагмент B, использующий NavHostFragment.
Я могу легко извлечь ViewModel из фрагмента A:
class FragmentA : Fragment(), KodeinAware {
protected val parentKodein by closestKodein()
override val kodeinContext = kcontext<Fragment>(this)
override val kodein: Kodein = Kodein.lazy {
extend(parentKodein)
import(myViewModelModule)
}
private val myViewModel: MyViewModel by instance()
}
Модуль также прост:
val myViewModelModule = Kodein.Module(TAG) {
bind<MyViewModel>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
ViewModelProvider(
this.context,
MyViewModelFactory(instance())
).get(
MyViewModel::class.java
)
}
bind<AMapper>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
AMapper()
}
}
Но я понятия не имею, как получить то же самое Экземпляр MyViewModel во фрагменте B, ближайший кодейн - это активность ...
Насколько я понимаю, мне нужно сделать что-то вроде
class FragmentB : Fragment(), KodeinAware {
override val kodeinContext = kcontext<Fragment>(this)
override val kodein: Kodein = Kodein.lazy {
extend(fragmentAKodein)
}
private val myViewModel: MyViewModel by instance()
}
Но я понятия не имею, как получить фрагмент Kodein.
Большое спасибо
Редактировать:
Это то, что я закончил делать:
class FragmentA : Fragment(), KodeinAware {
protected val parentKodein by closestKodein()
override val kodeinContext: KodeinContext<Fragment> by lazy { kcontext(childFragmentManager.findFragmentById(R.id.nav_host_containing_fragment_B) as Fragment)
}
override val kodein: Kodein = Kodein.lazy {
extend(parentKodein)
import(myViewModelModule)
}
private val myViewModel: MyViewModel by instance()
}
val myViewModelModule = Kodein.Module(TAG) {
bind<MyViewModel>() with scoped<BaseFragment>(AndroidLifecycleScope).singleton {
ViewModelProvider(
context.kodeinContext.value,
MyViewModelFactory(
instance()
)
).get(
MyViewModel::class.java
)
}
bind<AMapper>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
AMapper()
}
}
class FragmentB : Fragment(), KodeinAware {
override val kodeinContext: KodeinContext<Fragment> by lazy {
kcontext(parentFragment as Fragment)
}
override val kodein: Kodein = Kodein.lazy {
extend(fragmentAKodein)
}
private val myViewModel: MyViewModel by instance()
}
Благодаря ViewModelFactory, то же самое экземпляр MyViewModel является общим для всех фрагментов.
Но это обходной путь, так как Кодейн не считает, что маппер находится в той же области видимости, и создает новый экземпляр для каждого фрагмента ...