【问题标题】:Kodein - retrieve ViewModel fragment parentKodein - 检索 ViewModel 片段父级
【发布时间】:2020-04-12 13:51:43
【问题描述】:

我正在开发 Android,但我猜这个概念在每个平台上都是一样的。

我有一个片段 A 使用 NavHostFragment 托管另一个片段 B。

我可以轻松地从片段 A 中检索 ViewModel:

class FragmentA : Fragment(), KodeinAware {

    protected val parentKodein by closestKodein()
    override val kodeinContext = kcontext<Fragment>(this)

    override val kodein: Kodein = Kodein.lazy {
        extend(parentKodein)
        import(myViewModelModule)
    }

    private val myViewModel: MyViewModel by instance()
}

该模块也很简单:

val myViewModelModule = Kodein.Module(TAG) {

    bind<MyViewModel>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
        ViewModelProvider(
            this.context,
            MyViewModelFactory(instance())
        ).get(
            MyViewModel::class.java
        )
    }

    bind<AMapper>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
        AMapper()
    }
}

但我不知道如何在片段 B 中获取相同的 MyViewModel 实例,最接近的 kodein 是活动 ...

根据我的理解,我需要做类似的事情

class FragmentB : Fragment(), KodeinAware {

    override val kodeinContext = kcontext<Fragment>(this)

    override val kodein: Kodein = Kodein.lazy {
        extend(fragmentAKodein)
    }

    private val myViewModel: MyViewModel by instance()
}

但我不知道如何获取片段AKodein。

非常感谢

编辑:

这就是我最终做的:

class FragmentA : Fragment(), KodeinAware {

    protected val parentKodein by closestKodein()

    override val kodeinContext: KodeinContext<Fragment> by lazy { kcontext(childFragmentManager.findFragmentById(R.id.nav_host_containing_fragment_B) as Fragment)
    }

    override val kodein: Kodein = Kodein.lazy {
        extend(parentKodein)
        import(myViewModelModule)
    }

    private val myViewModel: MyViewModel by instance()
}

val myViewModelModule = Kodein.Module(TAG) {

    bind<MyViewModel>() with scoped<BaseFragment>(AndroidLifecycleScope).singleton {
        ViewModelProvider(
            context.kodeinContext.value,
            MyViewModelFactory(
                instance()
            )
        ).get(
            MyViewModel::class.java
        )
    }

    bind<AMapper>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
        AMapper()
    }
}

class FragmentB : Fragment(), KodeinAware {

    override val kodeinContext: KodeinContext<Fragment> by lazy {
        kcontext(parentFragment as Fragment)
    }

    override val kodein: Kodein = Kodein.lazy {
        extend(fragmentAKodein)
    }

    private val myViewModel: MyViewModel by instance()
}

感谢 ViewModelFactory,MyViewModel 的同一个实例在所有片段之间共享。

但这是一种解决方法,因为 Kodein 不认为映射器在同一范围内并为每个片段实例化一个新的...

【问题讨论】:

  • 两个问题:需要坚持使用kodein吗?你可以使用已经内置的 Android 架构组件(使用活动范围共享相同的视图模型)吗?
  • 我不必坚持使用 Kodein,但 MPP 功能很有趣(如果遇到太多问题,我会迁移到 Koin)我使用的是 Android 架构组件,但我想注入这个共享 ViewModel 而不是直接调用工厂。此外,我需要从子片段中获取主片段,以使其使用不是最干净的 ViewModelFactory 工作。

标签: android kodein


【解决方案1】:

使用自定义范围解决了我的问题:https://github.com/Kodein-Framework/Kodein-DI/issues/258

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    相关资源
    最近更新 更多