【问题标题】:Get sharedviewmodel in childfragment using Koin and navArgs使用 Koin 和 navArgs 在 childfragment 中获取 sharedviewmodel
【发布时间】:2019-11-28 17:58:29
【问题描述】:

我有一个基本上只包含底部导航和视图模型的片段。此视图模型由该片段中的所有子片段共享。我的 parentfragment 看起来有点像这样:

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 是这样在 koin 中注册的:

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 的情况下获取此视图模型?

【问题讨论】:

    标签: android android-fragments viewmodel koin


    【解决方案1】:

    如果你有一个带有容器和底部导航的片段,你可以试试这个技巧:

    在您的父片段中绑定 ViewModel:

    private val viewModel: UserDetailViewModel by viewModel()
    

    然后在包含在父片段容器中的子片段中:

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

    此 ViewModel 将使用您父片段的 viewModelStore,因此所有子片段的状态视图模型都相同

    Koin 2.1.0 版

    【讨论】:

    【解决方案2】:

    我遇到了同样的问题,当我在 koin 中注册模块时,我通过将 viewModel 更改为 single 来处理这个问题。在您的情况下,请尝试使用此代码进行修改

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

    如果你使用 viewModel 而不是 single,Koin 将在你调用 sharedViewModel() 时创建新对象。所以需要用户参数来重新创建视图模型。

    希望这能解决您的问题。

    【讨论】:

      【解决方案3】:

      在我的例子中,我希望 viewpager2 中的 5 个片段在 tablayout 片段的单个 ViewModel 中相互通信。

      之前我在 Koin 模块上将 viewmodel 声明为 Singletone。 Fragment 第一次获得了合适的视图模型。但是,一旦我在一些导航后重新启动该片段,视图模型的行为就不正常了。

      经过一些调试,我发现 viewmodelscope 无法正常工作,因为在我之前的视图销毁中清除了 vm,但是由于单音模式,一旦我回到同一个片段,同一个实例就会返回给我。

      通过搜索 viewmodelscope,我得到了这个问题跟踪页面:

      https://github.com/InsertKoinIO/koin/issues/506#issuecomment-521950186

      知道了,Koin 无法应对这种情况,而当前版本正是如此。所以我在那之后尝试了这个解决方案..

      我使用的 ViewModel 需要一个存储库作为构造函数参数。我的 Koin 模块声明如下,

      module {
          factory { SearchApi() }
          single<SearchRepo> { SearchRepoImpl(get()) } // It's dependant on SearchApi
      }
      

      我没有在 Koin DI 中声明视图模型。为了在所有片段中获取共享虚拟机,我使用了 androidx.fragment 委托:

      val viewmodel by activityViewModels\<SearchViewModel>()
      

      但是要使用存储库作为构造函数参数创建视图模型,我只使用了 Koin。

      class SearchViewModelFactory : ViewModelProvider.NewInstanceFactory(), KoinComponent {
          private val searchRepo: SearchRepo by inject()
          override fun <T : ViewModel> create(modelClass: Class<T>): T = SearchViewModel(searchRepo) as T
      }
      

      并在每个片段中获取共享虚拟机,

      val searchViewModel: SearchViewModel by activityViewModels { SearchViewModelFactory() }
      

      至少在 Koin 发布修复程序之前,这可能会对某人有所帮助.. 我目前的 Koin-android 版本:

      2.1.5

      使用的库:

      implementation "org.koin:koin-android:$koin_version"
      implementation "org.koin:koin-android-viewmodel:$koin_version"
      

      这个 codelab 帮助获得了 androidx 工件,

      https://developer.android.com/codelabs/basic-android-kotlin-training-shared-viewmodel#0

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多