0

我正在开发 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 不认为映射器在同一范围内并为每个片段实例化一个新的...

4

1 回答 1

0

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

于 2020-04-14T09:22:56.660 回答