Могу ли я управлять владельцем жизненного цикла, внедряя viewModel с помощью Koin?

У меня есть одно приложение 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 будет жить до смерти приложения.

По-видимому, вы можете указать ViewModelStore, или, по крайней мере, я слышал об этом.

EpicPandaForce 21.02.2019 19:04

Как насчет того, чтобы инициировать одну ViewModel в Activity, а фрагменты также имеют свои собственные ViewModels, мы можем заставить ViewModel взаимодействовать друг с другом. Что ты говоришь?

Chintan Soni 10.07.2019 12:25
7
2
1 872
3

Ответы 3

Начиная с 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, и вы можете отслеживать здесь.


А пока вот мое решение:

  1. Используйте navGraphViewModels() вместо viewModel() в Koin.
class DetailFr : Fragment() {
    private val vm: DetailViewModel by navGraphViewModels(R.id.main_nav_graph)
}
  1. Make ViwModel реализует 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)

Другие вопросы по теме