使用来自多个模块的依赖关系dagger 2.11 android

时间:2018-04-12 10:38:33

标签: android dependency-injection dagger-2 dagger

您好我在我的项目中的域包中分离了两个模块,并且有firebase insance服务类,它使用DaggerAppComponent手动注入。

然后我在我提到的两个模块上有两个注入依赖项。

ModuleOne具有称为存储的依赖关系,而ModuleTwo有一个称为委托者。

当试图在我的firebase服务类中注入这两个时,它会抱怨它无法从ModuleTwo找到并找到委托者注入器。

但是,如果我将委托方的提供方法接口复制到ModuleOne中,那么它会有效(现在会多次绑定它,但可以通过添加命名约定来轻松修复它)。

这是一种hacky方式,我不喜欢这样做,只是希望能够使用来自不同模块的任何依赖项。这可能吗?

以下是我的firebase服务类

class MyInstanceIdService : FirebaseInstanceIdService() {

    @Inject
    lateinit var delegator: AccountDelegatorContract

    @Inject
    lateinit var Storage: StorageContract

 override fun onCreate() {
        super.onCreate()
        AndroidInjection.inject(this)
    }
    override fun onTokenRefresh() {
        DaggerApplicationComponent.builder().application(application as MyApplication).build().inject(this)
        val refreshToken = FirebaseInstanceId.getInstance().token

//        val pianoStorage: PianoStorage = PianoStorage(this)
        sendTokenToServer(refreshToken, storage.getUniqueId())
    }

    private fun sendTokenToServer(refreshToken: String?, uniqueId: String) {
        //TODO: Send this new token to server

        delegator.sendPushToken(PushTokenRequest(refreshToken!!, uniqueId))
    }

这是moduleOne,它代表主要模块,它包含我的应用程序中多个域包中使用的依赖项。

@Module
abstract class MainModule {

 @ContributesAndroidInjector(modules = [AccountModule::class])
    @ViewScope
    abstract fun bindInstanceIdService(): MyInstanceIdService


      @Provides
        @Singleton
        @JvmStatic
        fun provideApplicationContext(application: Application): Context = application
 @Provides
        @Singleton
        @JvmStatic
        fun provideStorageData(storage: MainStorage): StorageContract = storage

}

这是特定于域包的ModuleTwo

@Module
abstract class AccountModule {
     @Module
    companion object {
        @ViewScope
        @JvmStatic
        @Provides
        fun providesAccountDelegator(accountDelegate: AccountDelegator): AccountDelegatorContract = accountDelegate

        @ViewScope
        @JvmStatic
        @Provides
        fun providesAccountControllerContract(accountNetworkController: AccountNetworkController): AccountControllerContract = accountNetworkController

    }

}

我的应用程序由不同的软件包组成,代表应用程序的一部分/域,例如帐户,用户,车辆,消息等,每个域都有自己的模块,用于定义与该域相关的特定依赖项。

我的问题是如何使用上面位于不同模块上的依赖项?

编辑:我的appCOmponent看起来像这样

@Singleton
@Component(modules = arrayOf(MainModule::class,
AccountModule ::class))

interface ApplicationComponent : AndroidInjector<DaggerApplication> {
    fun inject(MyApplication: MyApplication)
    fun inject(myInsanceIdService: MyInstanceIdService)
    override fun inject(instance: DaggerApplication)

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(applicaton: Application): Builder

        fun build(): ApplicationComponent
    }
}

1 个答案:

答案 0 :(得分:0)

您将AccountModule(使用ViewScope sope的提供方法)添加到AppComponent以及您的子组件(使用@ContributesAndroidInjector bindInstanceIdService声明),所以我想知道如何/为什么这样编译。首先,您应该从您的应用程序组件中删除AccountModule,因为它具有不同的范围,并且对您没有任何好处。

其次,您在DaggerApplicationComponent.inject(this)中致电MyInstanceIdService,但ApplicationComponent不包含inject(service : MyInstanceIdService)方法。同样,我不知道如何/为什么这会编译。如上所述,您注册了一个子组件(@ContributesAndroidInjector bindInstanceIdService)来注入您的服务,因此您应该使用它。您的应用程序组件甚至没有正确的范围来提供所有对象。

更糟糕的是,你在AppComponent中创建另一个 MyInstanceIdService,所以即使这样可行,你现在有2个单例组件提供你的“单身”的2个不同实例“对象。不要在其范围之外重新创建组件。使用MyApplication.getAppComponent()并使用那个!

因此,在从AppComponent中删除AccountModule后,您应该使您的应用程序实现HasServiceInjector,注入/返回调度注入器,就像您为活动所做的那样。然后使用AndroidInjection.inject(this)注入您的服务。

总结一下:

  • 检查您的范围。 @Singleton组件无法提供@ViewScope件事。
  • 不要在组件上注册具有不同范围的模块,否则无法使用它
  • 不要使用与您需要的范围不同的组件注入对象
  • 创建子组件时不要重新创建组件。使用现有的!
  • 如果您使用dagger.android,请不要自行创建组件,但要实现正确的界面并使用AndroidInjection.inject()