【问题标题】:Using dependencies from multiple modules dagger 2.11 android使用来自多个模块的依赖项 dagger 2.11 android
【发布时间】:2018-04-12 10:38:32
【问题描述】:

您好,我有两个模块在我的项目的域包中分开,并且有使用 DaggerAppComponent 手动注入自身的 firebase 实例服务类。

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

ModuleOne 有一个叫做 storage 的依赖,ModuleTwo 有一个叫做 delegator。

当尝试将这两个注入到我的 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
    }
}

【问题讨论】:

  • 尝试添加 ContributesAndroidInjector 和 AndroidInjection.inject(this) 仍然没有乐趣

标签: android dependency-injection dagger-2 dagger


【解决方案1】:

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

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

更糟糕的是,您在 MyInstanceIdService 中创建了 另一个 AppComponent,因此即使这可行,您现在也有 2 个单例组件提供 2 个不同的“单例”对象实例。不要重新创建超出其范围的组件。使用MyApplication.getAppComponent() 并使用那个!

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

总结一下:

  • 检查您的示波器。 @Singleton 组件无法提供 @ViewScope 的东西。
  • 不要在组件上注册具有不同作用域的模块,它们无论如何都不能使用它
  • 不要注入具有与您需要的范围不同的组件的对象
  • 创建子组件时不要重新创建组件。使用现有的!
  • 如果您使用dagger.android,则不要自己创建组件,而是实现正确的接口并使用AndroidInjection.inject()

【讨论】:

  • 根据我的理解以及我看到的各种来源和教程,您需要在 appComponent 中包含模块。如果你把它拿出来,那么模块是如何初始化和使用的呢?每篇文章都指出它是在 AppComponent 中初始化的。我上面的代码也编译得很好,除了错误说我的委托人不能在没有提供的情况下提供。虽然存储提供完美。我现在尝试将它们的范围都更改为 @ViewScope 并且仍然遇到相同的问题。
  • 并且还删除了 DaggerAppComponent 构建器,只包含了 AndroidInjection.inject(this) 并且没有喜悦仍然同样的错误,特别是关于我位于 moduleTwo 上的委托人
  • 另外,我上面的代码已经有了 inject(service: InstanceIdSerice)
猜你喜欢
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 2016-08-01
  • 2019-08-28
相关资源
最近更新 更多