Могу ли я управлять владельцем жизненного цикла, вводя 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 будет жить до смерти приложения.
3 ответа
С навигацией 2.1.0-alpha02
:
Теперь вы можете создавать ViewModels, которые находятся на уровне навигационного графика, с помощью делегата свойства navGraphViewModels() для пользователей Kotlin или с помощью API-интерфейса getViewModelStore (), добавленного в NavController.
Вы можете найти журнал изменений здесь и документ.
К сожалению, Коин не может поддерживать эту функцию, так как viewModel()
или же sharedViewModel()
был связан с деятельностью. Но поддержка nav уже запланирована в 2.1.x
и вы можете отслеживать здесь.
А пока вот мое решение:
- использование
navGraphViewModels()
вместоviewModel()
в коине.
class DetailFr : Fragment() {
private val vm: DetailViewModel by navGraphViewModels(R.id.main_nav_graph)
}
- Сделать ViwModel реализует
KoinComponent
так что мы можем использоватьby inject()
вместо того, чтобы вводить с помощью конструктора.
class DetailViewModel : ViewModel(), KoinComponent {
private val repo: DetailRepository by inject()
// othetr objects you need
}
Надеюсь, это поможет
Сделать это можно, используя новую версию Koin(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)
В версии для коинов
3.1.3
есть новая функция расширения
koinNavGraphViewModel
.
просто добавьте следующую зависимость
implementation "io.insert-koin:koin-androidx-navigation:$koin_version"
Его можно использовать так
private val viewModel: MyViewModel by koinNavGraphViewModel(R.id.my_graph)