Как правильно создать приложение ViewModel с параметром SavedStateHandle

Я объявляю ViewModel с SavedStateHandle в качестве параметра в модулях коинов.

  1. в модулях коинов
viewModel { (handle: SavedStateHandle) -> CacheProvider(handle) }

viewModel { SomeFragmentUsedViewModel(get()) }
  1. И инициируйте его в Activity
lateinit var cacheProvider: CacheProvider

  1. Повторно использовать в SomeFragment
private val viewModel: SomeFragmentUsedViewModel by inject()

private val cacheProvider: CacheProvider by sharedViewModel()
  1. При переходе в SomeFragment приложение вылетало при доступе к ViewModel:
2020-04-30 22:04:04.858 26677-26677/com.ncbportal.sit E/[Koin]: Instance creation error : could not create instance for [Factory:'com.ncb.common.viewmodel.CacheProvider']: org.koin.core.error.NoParameterFoundException: Can't get parameter value #0 from org.koin.core.parameter.DefinitionParameters@a37a822
        org.koin.core.parameter.DefinitionParameters.elementAt(DefinitionParameters.kt:32)
        org.koin.core.parameter.DefinitionParameters.component1(DefinitionParameters.kt:34)
        com.ncbportal.di.ViewModelModuleKt$viewModelModule$1$77.invoke(Unknown Source:11)
        com.ncbportal.di.ViewModelModuleKt$viewModelModule$1$77.invoke(Unknown Source:4)
        org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:50)
        org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
        org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:87)
        org.koin.core.scope.Scope.resolveInstance(Scope.kt:214)
        org.koin.core.scope.Scope.get(Scope.kt:181)
        com.ncbportal.di.ViewModelModuleKt$viewModelModule$1$76.invoke(ViewModelModule.kt:117)
        com.ncbportal.di.ViewModelModuleKt$viewModelModule$1$76.invoke(Unknown Source:4)
        org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:50)
        org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
        org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:87)
        org.koin.core.scope.Scope.resolveInstance(Scope.kt:214)
        org.koin.core.scope.Scope.get(Scope.kt:181)
        com.ncbportal.deposit.fragment.ApplyTermDepositFragment$$special$$inlined$inject$1.invoke(ComponentCallbackExt.kt:51)
        kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)


2020-04-30 22:04:04.861 26677-26677/com.ncbportal.sit E/[Koin]: Instance creation error : could not create instance for [Factory:'com.ncbportal.deposit.viewmodel.ApplyTermDepositViewModel']: org.koin.core.error.InstanceCreationException: Could not create instance for [Factory:'com.ncb.common.viewmodel.CacheProvider']
        org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:59)
        org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
        org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:87)
        org.koin.core.scope.Scope.resolveInstance(Scope.kt:214)
        org.koin.core.scope.Scope.get(Scope.kt:181)
        com.ncbportal.di.ViewModelModuleKt$viewModelModule$1$76.invoke(ViewModelModule.kt:117)
        com.ncbportal.di.ViewModelModuleKt$viewModelModule$1$76.invoke(Unknown Source:4)
        org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:50)
        org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
        org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:87)
        org.koin.core.scope.Scope.resolveInstance(Scope.kt:214)
        org.koin.core.scope.Scope.get(Scope.kt:181)
        com.nextbank.ncbportal.deposit.fragment.ApplyTermDepositFragment$$special$$inlined$inject$1.invoke(ComponentCallbackExt.kt:51)
        kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)

Поиск по всем вопросам репозитория коинов, похоже, не является определенным способом создания модели ViewModel (в моем случае CacheProvider) для всех фрагментов и ViewModel для доступа.

Кто-нибудь знает об этом?


person Robert    schedule 30.04.2020    source источник


Ответы (2)


Согласно этому сообщению, будет новая версия коина, обеспечивающая некоторую функцию расширения для создания жизнь проще. Следуйте инструкциям после добавления этих функций расширения в качестве обходного пути, пока он работает.

Но основная проблема заключается в том, что я пытаюсь поместить этот общий для приложения CacheProvider в качестве параметра в SomeFragmentUsedViewModel. Это кажется невозможным для инъекции. Итак, поток данных должен быть:

  1. в модуле коинов
viewModel { (handle: SavedStateHandle) -> CacheProvider(handle) }

viewModel { SomeFragmentUsedViewModel() }

  1. В действии
private val cacheProvider: CacheProvider by stateViewModel {
        parametersOf(
            SavedStateHandle()
        )
    }
  1. Повторно использовать в SomeFragment
private val viewModel: SomeFragmentUsedViewModel by inject()

private val cacheProvider: CacheProvider by stateSharedViewModel()

  1. Перенести данные из cacheProvider в viewModel. Таким образом, фрагмент работает как мост между двумя ViewModels.
cacheProvider.data?.let { safeData ->
  viewModel.initDataWith(safeData)

}
person Robert    schedule 01.05.2020

Кажется, вы пытаетесь передать модель просмотра в другую модель просмотра? Не очень хорошо (какое приложение в широком масштабе оно будет обслуживать?). Ваш CacheProvider должен отличаться от модели представления (репозиторий одноэлементного кеша для всего приложения?).

Я предлагаю вам попробовать это следующим образом: Koin sharedViewModel с SavedStateHandle

В конце концов, ваш SomeFragmentUsedViewModel должен управлять сохранением / восстановлением состояния, а не CacheProvider. Последним, вероятно, должно быть то, что он называется: поставщик кеша, без доступа к механизму сохранения / восстановления состояния просмотра.

Несколько важно сказать, что вышеупомянутое работает с koin ver 2.1.5.

person ror    schedule 02.05.2020
comment
Спасибо за ответ! Да, CacheProvide должен быть кешем для приложений. И я пытаюсь создать кеш для приложений, используя shareViewModel с SavedStateHandle. Вариант использования - это Activity, хранящая данные (через shareViewModel) для своих дочерних фрагментов (по крайней мере, для 10 фрагментов). Нашла ваш пост и уже попробовала. Все еще экспериментирую. - person Robert; 05.05.2020