Получите sharedviewmodel в дочернем фрагменте с помощью Koin и navArgs

У меня есть фрагмент, который в основном содержит только нижнюю навигацию и модель просмотра. Эта модель просмотра используется всеми дочерними фрагментами в этом фрагменте. Мой родительский фрагмент выглядит примерно так:

class UserDetailFragment : Fragment() {

    private val args: UserDetailFragmentArgs by navArgs()
    private val userDetailViewModel: UserDetailViewModel by viewModel { parametersOf(args.user) }

    //standard code
    //onCreateActivity where I do some basic stuff like switching the fragments
}

Viewmodel регистрируется в коине так:

val viewModelModule = module {
        /* other viewmodels */
        viewModel { (user: UserModel) -> UserDetailViewModel(get(), get(), user) }
    }

Затем у нас есть дочерние фрагменты, которые я пытаюсь определить следующим образом:

class UserAlbumsFragment : Fragment() {

    private val userDetailViewModel: UserDetailViewModel by sharedViewModel() //THIS LINE ISN'T WORKING

    //standard code again
}

Как видите, одна строка не работает, я попытался написать ее так:

private val userDetailViewModel: UserDetailViewModel 
   by sharedViewModel(from = { parentFragment as ViewModelStoreOwner })

но я продолжаю получать эту ошибку:

Caused by: org.koin.core.error.NoParameterFoundException: Can't get parameter value #0 from org.koin.core.parameter.DefinitionParameters@426de94
        at org.koin.core.parameter.DefinitionParameters.elementAt(DefinitionParameters.kt:31)
        at org.koin.core.parameter.DefinitionParameters.component1(DefinitionParameters.kt:33)
        at com.kvw.technicaltestmediamonks.di.KoinModules$viewModelModule$1$5.invoke(Unknown Source:11)
        at com.kvw.technicaltestmediamonks.di.KoinModules$viewModelModule$1$5.invoke(KoinModules.kt:37)
        at org.koin.core.instance.DefinitionInstance.create(DefinitionInstance.kt:54)

Как мне получить эту модель просмотра без повторного определения userModel?


person Typhaon    schedule 28.11.2019    source источник


Ответы (2)


Если у вас есть фрагмент с контейнером и нижней навигацией, вы можете попробовать этот трюк:

В родительском фрагменте вы привязываете ViewModel:

private val viewModel: UserDetailViewModel by viewModel()

И после в вашем дочернем фрагменте, который содержится в контейнере вашего родительского фрагмента:

private val viewModel by lazy { requireParentFragment().getViewModel<UserDetailViewModel>() }

Эта ViewModel будет использовать viewModelStore вашего родительского фрагмента, поэтому это будет одно и то же состояние viewModel для всех дочерних фрагментов.

Версия коина 2.1.0

person Krasavello13    schedule 25.02.2020
comment
Возможно ли это с родительской Activity и дочерними элементами в виде фрагментов? - person James121; 09.03.2021
comment
@ James121 В этом случае используйте стандартный API insert-koin.io/ docs / reference / koin-android / - person Krasavello13; 10.03.2021

У меня была такая же проблема, и я решил эту проблему, изменив viewModel на single, когда я зарегистрировал модуль в koin. В вашем случае попробуйте изменить с помощью этого кода

val viewModelModule = module {
    /* other viewmodels */
    single { (user: UserModel) -> UserDetailViewModel(get(), get(), user) }
}

Если вы используете viewModel вместо single, Koin создаст новый объект, когда вы вызовете sharedViewModel (). Таким образом, пользовательский параметр необходим для воссоздания модели представления.

Надеюсь, это решит вашу проблему.

person thomyfarhan    schedule 26.12.2019