没有注射器工厂绑定@ContributesAndroidInjector

时间:2018-08-08 19:12:12

标签: android dagger-2 dagger

请不要标记此重复项,我已经阅读了有关此问题的所有其他答案。我不是在问这个问题意味着什么,而是在问为什么这个特定的代码会产生此错误。

我正在尝试制作一个以Activity作为其父元素的SessionComponent组件/注入器:

AppComponent:

@Singleton
@Component(modules = [AppModule::class, AndroidSupportInjectionModule::class])
interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(ltiApp: LTIApp): Builder
        fun build(): AppComponent
    }

SessionComponent:

@SessionScope
@Component(
        dependencies = [AppComponent::class],
        modules = [SessionModule::class, CommentaryModule::class, EducationCenterModule::class])
interface SessionComponent {

EducationCenterModule

@dagger.Module
abstract class EducationCenterModule {
    @EducationScope
    @ContributesAndroidInjector()
    abstract fun educationCenterActivity(): EducationCenterActivity
}

即使我在@ContributesAndroidInjector中有Module,怎么会因喷油器工厂而出错?

  

由于:java.lang.IllegalArgumentException:没有注射器工厂   开往   类

1 个答案:

答案 0 :(得分:2)

如果可能,将@ContributesAndroidInjector移至AppModule,这可能会涉及AppComponent和SessionComponent之间的某些重构。


dagger.android通过在Activity上调用getApplication(),将其强制转换为HasActivityInjector,然后在(code)上调用activityInjector().inject(activity)来注入Activity实例。反过来,使用DaggerApplication(或dagger.android入门页面上的代码)will inject a DispatchingAndroidInjector<Activity>的应用程序,其中injects a Map<Class, AndroidInjector.Builder>built using multibindings。通过it's possible to inject into this map directly,您也可以使用@ContributesAndroidInjector(如此处所做的操作)作为生成多重绑定和子组件的快捷方式。

尽管@ContributesAndroidInjector中绑定了@Module,但是您有两个顶级组件:AppComponent和SessionComponent。 dagger.android尚未为此做好准备:您的应用程序可能使用AppComponent进行注入,并且由于您尚未将EducationCenterModule安装到AppComponent中,因此多绑定映射将不包含您的@ContributesAndroidInjector方法安装的绑定。

这可能需要进行一些重构,但是出于重要的原因:通过意图,后向堆栈和活动管理,Android保留在需要时重新创建Activity实例的权利。尽管您的Application子类可能会保证届时存在一个AppComponent(通过在onCreate中创建和存储该组件),但并不能保证SessionComponent将存在,也无法为Android创建的Activity实例建立任何确定的方式找到它可以使用的SessionComponent。


解决此问题的最常用方法是将Android生命周期与您的业务逻辑分开,,例如dagger.android在自己的生命周期中管理Android组件,而这些Android组件会创建/销毁根据需要SessionComponent和其他业务逻辑类。如果您需要Service,ContentProvider或BroadcastReceiver类,这也可能很重要,因为这些类肯定只能访问该应用程序,并且可以恢复或创建自己的会话。最后,这还意味着Session的持续时间必须比Activity实例的持续时间长,这可能意味着在Android销毁Activity之前不会对您的Session进行垃圾回收,也可能意味着您有多个并发的SessionComponent实例。

编辑/阐述:首先,您需要确定会话是否比活动有效,活动比会话有效,或两者都不可行。我敢打赌它“都不是”,这很好:到那时,我将编写一个可注入的@Singleton SessionManager,将其插入AppComponent并管理SessionComponent的创建,重新创建和获取。然后,我尝试将其划分,以便大多数业务逻辑都在SessionComponent端,并且通过调用sessionManager.get()。getBusinessObject()可以从SessionComponent访问它。这也很适合您说实话,因为使用Robolectric或Java可能易于对业务逻辑端进行单元测试,而Android端可能需要在仿真器中进行仪表测试。而且,当然,您可以在AppComponent模块中使用@Provides方法来将SessionComponent,BusinessObject或任何其他相关实例拉出SessionManager端。

但是,如果您100%确定要使SessionComponent成为Activity的容器,并且您不介意在Application子类中管理会话的创建和删除。在这种情况下,您可以编写Application子类来实现HasActivityInjector(等),而不是使用DaggerApplication,然后将activityInjector()方法委托给您创建的SessionComponent实例上的类。这意味着AppComponent将不再包含AndroidSupportInjectionModule,因为您不再注入DispatchingAndroidInjector或其地图。但是,这是一个不寻常的结构,会对您的应用程序产生影响,因此,在进行下一步操作之前应仔细考虑组件结构,如果选择非标准路线,则应大量记录下来。

相关问题