Android Dagger2继承的子组件多绑定

Android Dagger2继承的子组件多绑定,android,kotlin,dagger-2,dagger,Android,Kotlin,Dagger 2,Dagger,希望在日复一日地研究这个非常感兴趣的主题“继承子组件多绑定”之后,能在这里找到一些帮助,这是该页面中的最后一个主题 根据官方文件: 子组件可以将元素添加到其父组件中绑定的多绑定集合或映射中。发生这种情况时,集合或映射根据其注入的位置而不同。当将其注入在子组件上定义的绑定中时,则具有子组件的mu定义的值或条目ltibindings以及父组件的多绑定定义的绑定。当它被注入父组件上定义的绑定时,它只有在那里定义的值或条目 换句话说,如果父组件具有一个多绑定集或映射,并且子组件具有与该多绑定的绑定,则这

希望在日复一日地研究这个非常感兴趣的主题“继承子组件
多绑定”
之后,能在这里找到一些帮助,这是该页面中的最后一个主题

根据官方文件:

子组件
可以将元素添加到其父组件中绑定的
多绑定
集合或映射中。发生这种情况时,集合或映射根据其注入的位置而不同。当将其注入在
子组件
上定义的绑定中时,则具有子组件的
mu定义的值或条目ltibindings
以及父组件的
多绑定定义的绑定。当它被注入父组件上定义的绑定时,它只有在那里定义的值或条目

换句话说,如果父
组件
具有一个
多绑定集或映射
,并且
子组件
具有与该多绑定的绑定,则这些绑定将链接/添加到父映射中,具体取决于这些绑定在dagger范围内的注入位置(如果有)

问题就在这里。 在Android应用程序中使用
dagger version 2.24
,使用
Kotlin
。我有一个
ApplicationComponent
,使用了新的
@Component.Factory
方法。ApplicationComponent安装了
AndroidSupportInjunctionModule

我还有一个使用新的
@Component.Factory
方法的
ActivitySubComponent
,这个方法使用模块注释的
subComponents
参数链接到AppComponent。 此ActivitySubComponent通过如下绑定提供了一个
ViewModel

@Binds
@IntoMap
@ViewModelKey(MyViewModel::class)
fun provideMyViewModel(impl: MyViewModel): ViewModel
@ViewModelKey
是一个自定义匕首注释

我还有一个像这样实现的ViewModelFactory

@Singleton
class ViewModelFactory @Inject constructor(
    private val viewModelsToInject: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T = 
    viewModelsToInject[modelClass]?.get() as T
}
@Singleton
类ViewModelFactory@Inject构造函数(
私有val viewModelsToInject:映射
):ViewModelProvider.Factory{
重写趣味创建(modelClass:Class):T=
ViewModelsToInjection[modelClass]?.get()作为T
}
普通ViewModelFactory

这里的区别是我在一个AppComponents模块中提供了这个ViewModelFactory。但是ActivitySubComponent中的绑定viewModels没有添加到AppComponent中的ViewModelFactory映射中

换句话说,文档所描述的根本没有发生

如果我将viewModels绑定移动到任何AppComponent模块中,那么所有模块都可以工作


您知道这里会发生什么吗。

您正在将您的
ViewModelProvider.Factory
范围限定为
@Singleton
。这确保了它将被创建并保存在
@Singleton
组件中


删除作用域是安全的,因为它不保留任何状态,并且允许在需要时使用正确的绑定集创建工厂。

文档是准确的。虽然Dagger的操作方式与生成set/Map MultiBindind时所描述的方式相同,但它的工作方式不同,因为您处于一个困境中

举例说明 假设您有以下模块:

/**
 * Binds ViewModelFactory as ViewModelProvider.Factory.
 */
@Module
abstract class ViewModelProviderModule {

    @Binds abstract fun bindsViewModelFactory(impl: ViewModelFactory): ViewModelProvider.Factory
}

/**
 * For the concept, we bind a factory for an AppViewModel 
 * in a module that is included directly in the AppComponent.
 */ 
@Module
abstract class AppModule {

    @Binds @IntoMap
    @ViewModelKey(AppViewModel::class)
    abstract fun bindsAppViewModel(vm: AppViewModel): ViewModel
}

/**
 * This module will be included in the Activity Subcomponent.
 */
@Module
abstract class ActivityBindingsModule {

    @Binds @IntoMap
    @ViewModelKey(MyViewModel::class)
}

/**
 * Generate an injector for injecting dependencies that are scoped to MyActivity.
 * This will generate a @Subcomponent for MyActivity.
 */
@Module
abstract class MyActivityModule {

    @ActivityScoped
    @ContributesAndroidInjector(modules = [ActivityBindingsModule::class])
    abstract fun myActivity(): MyActivity
}
如果要将
ViewModelProvider.Factory
注入到应用程序类中,那么
Map
中应该提供什么?因为您是在
AppComponent
的范围内注入,所以
ViewModelFactory
将只能创建
AppViewModel
的实例,而不能创建
MyViewModel
since绑定在子组件中定义

如果在
MyActivity
中插入
ViewModelProvider.Factory
,那么由于我们都在
AppComponent
MyActivitySubcomponent
的范围内,那么新创建的
ViewModelFactory
将能够创建
AppViewModel
MyViewModel
的两个实例

这里的问题是
ViewModelFactory
被注释为
@Singleton
。因此,ViewModelFactory的单个实例被创建并保存在
AppComponent
中。由于
MainActivityComponent
AppComponent
的子组件,因此它继承了该Singleton和不会创建包含带有2
ViewModel
绑定的映射的新实例

下面是正在发生的事情的顺序:

  • 调用了MyApplication.onCreate()
  • 。您可以创建
    DaggerAppComponent
  • DaggerAppComponent
    的构造函数中,Dagger构建了一个映射,该映射具有
    提供者的映射
  • 它使用该映射作为
    ViewModelFactory
    的依赖项,然后将其保存在组件中
  • 在注入活动时,Dagger检索对该
    ViewModelFactory
    的引用,并直接注入它(它不会修改映射)
  • 你能做些什么使它按预期工作
  • 删除
    ViewModelFactory
    上的
    @Singleton
    注释。这确保Dagger每次需要时都会创建一个
    ViewModelFactory
    的新实例。这样,
    ViewModelFactory
    将收到一个包含这两个绑定的映射
  • ViewModelFactory
    上的
    @Singleton
    注释替换为
    @reusible
    。这样,Dagger将尝试重用
    ViewModelProvider
    的实例,而不保证在整个应用程序中使用唯一的实例。如果检查生成的代码,您将注意到不同的ins实例保存在每个
    AppComponent
    MyActivitySubcomponent
  • 问题 这是因为地图是在AppComponent中创建的,而您正在子组件中将ViewModel添加到地图中