У меня есть одно приложение Activity.
Я хочу привязать viewModel к жизненному циклу родительского фрагмента (FlowFragmentLogin) и поделиться им с дочерними фрагментами (CellFragment, InfoFragment, etc). Так что, когда я перехожу с FlowFragmentLogin на FlowFragmentMain, вызывалась viewModel onCleared().
Но единственный способ, который я нашел, - это разделить viewModel между Activity и его фрагментами: https://insert-koin.io/docs/1.0/documentation/koin-android/index.html
И никакого контроля над владельцами жизненного цикла. Для меня это неприемлемо, хотя бы потому, что эта viewModel будет жить до смерти приложения.
Как насчет того, чтобы инициировать одну ViewModel в Activity, а фрагменты также имеют свои собственные ViewModels, мы можем заставить ViewModel взаимодействовать друг с другом. Что ты говоришь?
Начиная с Navigation 2.1.0-alpha02:
You can now create ViewModels that are scoped at a navigation graph level via the by navGraphViewModels() property delegate for Kotlin users or by using the getViewModelStore() API added to NavController.
Вы можете найти журнал изменений здесь и документ.
К сожалению, Koin не может поддерживать эту функцию, поскольку viewModel() или sharedViewModel() были связаны с Activity. Но поддержка навигации уже запланирована в 2.1.x, и вы можете отслеживать здесь.
А пока вот мое решение:
navGraphViewModels() вместо viewModel() в Koin.class DetailFr : Fragment() {
private val vm: DetailViewModel by navGraphViewModels(R.id.main_nav_graph)
}
KoinComponent, так что мы можем использовать by inject() вместо инъекции конструктором.class DetailViewModel : ViewModel(), KoinComponent {
private val repo: DetailRepository by inject()
// othetr objects you need
}
Надеюсь, это поможет
Сделать это можно, используя новую версию Коин (2.1.0) и немного магии :)
Все, что вам нужно, это добавить эту функцию расширения:
inline fun <reified VM : ViewModel> Fragment.sharedGraphViewModel(
@IdRes navGraphId: Int,
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
) = lazy {
val store = findNavController().getViewModelStoreOwner(navGraphId).viewModelStore
getKoin().getViewModel(ViewModelParameter(VM::class, qualifier, parameters, null, store, null))
}
И теперь вы можете просто получить свою ViewModel из вложенного графа:
private val viewModel: MyViewModel by sharedGraphViewModel(R.id.my_graph)
В версии Koin 3.1.3 появилась новая функция расширения koinNavGraphViewModel.
просто добавьте следующую зависимость
implementation "io.insert-koin:koin-androidx-navigation:$koin_version"
Его можно использовать так
private val viewModel: MyViewModel by koinNavGraphViewModel(R.id.my_graph)
По-видимому, вы можете указать ViewModelStore, или, по крайней мере, я слышал об этом.