【问题标题】:Can I manage lifecycle owner, injecting viewModel with Koin?我可以管理生命周期所有者,用 Koin 注入 viewModel 吗?
【发布时间】:2019-05-22 22:49:02
【问题描述】:

我有一个 Activity 应用程序。

我想将 viewModel 绑定到父片段生命周期(FlowFragmentLogin),并与子片段(CellFragmentInfoFragmentetc)共享。这样当我从 FlowFragmentLogin 移动到 FlowFragmentMain 时,就会调用 viewModel onCleared()

但我发现的唯一方法是在 Activity 之间共享 viewModel,它是 Fragments: https://insert-koin.io/docs/1.0/documentation/koin-android/index.html

并且无法控制生命周期所有者。这对我来说是不可接受的,至少因为这个 viewModel 将一直存在到应用程序死亡。

【问题讨论】:

  • 显然你可以指定 ViewModelStore,或者至少我听说过。
  • 在Activity中发起一个ViewModel怎么样,fragment也有自己的ViewModel,我们可以让ViewModel互相对话。你说什么?

标签: android kotlin viewmodel lifecycle koin


【解决方案1】:

在 Koin 版本3.1.3 中有一个新的扩展函数koinNavGraphViewModel

只需添加以下依赖项

implementation "io.insert-koin:koin-androidx-navigation:$koin_version"

可以这样使用

private val viewModel: MyViewModel by koinNavGraphViewModel(R.id.my_graph)

【讨论】:

    【解决方案2】:

    您可以通过使用新版本的 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】:

      自导航2.1.0-alpha02:

      您现在可以通过 Kotlin 用户的 by navGraphViewModels() 属性委托或使用添加到 NavController 的 getViewModelStore() API 创建在导航图级别范围内的 ViewModel。

      您可以找到更改日志heredocument

      很遗憾 Koin 无法支持该功能,因为 viewModel()sharedViewModel() 已绑定到 Activity。但是2.1.x已经计划支持nav,你可以追踪here


      现在这是我的解决方案:

      1. 在 Koin 中使用 navGraphViewModels() 而不是 viewModel()
      class DetailFr : Fragment() {
          private val vm: DetailViewModel by navGraphViewModels(R.id.main_nav_graph)
      }
      
      1. 让 ViwModel 实现 KoinComponent,这样我们就可以使用 by inject() 而不是构造函数注入。
      class DetailViewModel : ViewModel(), KoinComponent {
      
          private val repo: DetailRepository by inject()
          // othetr objects you need
      }
      

      希望这会有所帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 1970-01-01
        • 2021-07-23
        • 1970-01-01
        • 2012-11-24
        相关资源
        最近更新 更多