Kotlin Dagger 2在活动和片段之间共享ViewModel

Kotlin Dagger 2在活动和片段之间共享ViewModel,kotlin,mvvm,code-injection,dagger,Kotlin,Mvvm,Code Injection,Dagger,正如标题中提到的,我有一个匕首2注射的问题。我有一个活动和多个片段。我正在尝试与每个子片段共享活动的ViewModel。我的解决方案基于谷歌的Android架构ToDo示例。我已将ViewModelFactory创建为 如果您跳转到链接,您将看到在他们的解决方案中,每个活动和片段都有一个单独的ViewModel。他们没有展示如何处理像我这样的情况。我对ActivityModule的实现如下所示: @Module abstract class SampleModule { @Cont

正如标题中提到的,我有一个匕首2注射的问题。我有一个活动和多个片段。我正在尝试与每个子片段共享活动的ViewModel。我的解决方案基于谷歌的Android架构ToDo示例。我已将ViewModelFactory创建为

如果您跳转到链接,您将看到在他们的解决方案中,每个活动和片段都有一个单独的ViewModel。他们没有展示如何处理像我这样的情况。我对ActivityModule的实现如下所示:

 @Module
 abstract class SampleModule {
    @ContributesAndroidInjector(
            modules = [
                ViewModelBuilder::class
            ]
    )
    internal abstract fun sampleActivity(): SampleActivity

    @Binds
    @IntoMap
    @ViewModelKey(SampleViewModel::class)
    abstract fun bindViewModel(viewModel: SampleViewModel): ViewModel
}
我的活动扩展了
daggerappcompativity
和fragment
DaggerFragment
,如下所示,我的视图注入模型看起来很简单

class SampleActivity : DaggerAppCompatActivity() {

   @Inject
   lateinit var viewModel: SampleViewModel
   ...
我找不到解决问题的网络解决方案。我是匕首的新手。我已经尝试过实现Subcomponent,但它仍然不起作用,因为到目前为止我搜索的所有示例都没有使用
DaggerApplication
DaggerAppCompativity
和我的注入方式。请提出任何解决方案,或者如果子组件的方式是正确的,请向我展示如何在我当前的架构中实现它


非常感谢您。

@silaros88我面临着同样的问题,在单个活动应用程序中在多个框架网之间共享一个ViewModel,我解决了玩
ViewmModelStoreOwner的问题

解决问题的步骤

  • 这里可以看到他们是如何注入
    ViewModelProvider.Factory
    而不是
    ViewModel
  • 使用以下两个选项之一检索desire ViewModel:

    • viewModels(requirectivity()){Injected ViewModelProvider.Factory}
    • ViewModelProvider(requireActivity(),注入的ViewModelProvider.Factory).get(SharedDesireViewModel::class.java)
示例:

选项#1:

片段a.kt

class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
片段b.kt

class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
选项2:

片段a.kt

class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
片段b.kt

class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by viewModels({requireActivity()}) { viewModelProviderFactory }

    ......
class FragmentA: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......
class FragmentB: DaggerFragment() {

    @Inject
    lateinit var viewModelProviderFactory: ViewModelProvider.Factory

    private val mainViewModel: MainViewModel by lazy {
    ViewModelProvider(requireActivity(), viewModelProviderFactory)
        .get(MainViewModel::class.java)
    }

    ......

我用稍微不同的方法解决了这个问题。 因为碎片和活动都有匕首模块。 在ActivityModule中,我提供了SharedView模型,如下所示

@Module
class ActivityModule(private val activity: AppCompatActivity) 
{

  @Provides
  fun provideMainSharedVieModel() : MainSharedViewModel = 
     ViewModelProvider(activity).get(MainSharedViewModel::class.java)
 }
在我的片段模块中,我再次提供如下相同的模型:

@Module
class FragmentModule(private val fragment: Fragment) 
{

  @Provides
  fun provideMainSharedVieModel() : MainSharedViewModel = 
     ViewModelProvider(fragment.activity!!).get(MainSharedViewModel::class.java)
 }

由于ViewModels存储在以activity或fragments为键的映射中,因此在fragment模块中为sharedViewModel提供“fragment.activity!!”不会创建viewmodel的新实例,它只会将已实例化的共享viewmodel返回到片段。

您的解释较少,错误到底是什么?若有异常,发布您的
跟踪
,您是否在组件中添加了SampleModule?如果您使用的是daggerApplication,您是否从清单文件中启用了它?您的依赖关系图和对象图都设置正确了吗?