Rgfvfk Iff
Rgfvfk Iff

Reputation: 1609

Dagger Injection for dependent components

I am using Dagger2 and I want to know if it is possible to use the new Android Injector for dependent components? I have seen a few tutorials that use subcomponents and the base App component will just inject everything.

AppComponent

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class])
interface ApplicationComponent {

    fun inject(app: App)

    @Component.Builder
    interface Builder {
        fun build(): ApplicationComponent

        @BindsInstance
        fun app(app: Context): Builder
    }
}

QueueComponent

@QueueScope
@Component(dependencies = arrayOf(ApplicationComponent::class), modules = [ScreenBindingModule::class])
interface QueueComponent {
}

ScreenBindingModule

@Module
abstract class ScreenBindingModule {
    @ContributesAndroidInjector()
    abstract fun queueActivity(): QueueActivity
}

In the onCreate I have added AndroidInjection.inject(this) but the problem is that the app crashes with the exception:

Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class....

Upvotes: 0

Views: 326

Answers (2)

Jeff Bowman
Jeff Bowman

Reputation: 95654

No, this will not work without more configuration. As in AndroidInjection.inject:

Application application = activity.getApplication();
if (!(application instanceof HasActivityInjector)) { /* ... */ }

Given an Activity there's no easy way to determine which wider-than-Activity-scoped object should be used to create the Activity's subcomponent, so dagger.android tries to cast the Application to the type HasActivityInjector. Your Application evidently exposes HasActivityInjector to get that error message—likely by marking DaggerApplication or your custom subclass of DaggerApplication in your manifest—but that implementation just returns the DispatchingAndroidInjector<Activity> that searches a multibindings map.

Though @ContributesAndroidInjector automatically installs into that map, each of your Components (ApplicationComponent and QueueComponent) contains a different map, and your DaggerApplication only consults the one in ApplicationComponent.

In order to make this work with component dependencies, you would need to have your Application subclass's activityInjector method return a different AndroidInjector implementation, which creates/fetches a QueueComponent instance and reads the multibound Maps (which would necessarily be exposed on QueueComponent). Unfortunately, there isn't really a way to bind multiple elements into your ApplicationComponent's existing multibound map, as tracked in https://github.com/google/dagger/issues/687, so making this work would involve a custom AndroidInjector implementation at least.

Upvotes: 1

Darthoo
Darthoo

Reputation: 311

 @ContributesAndroidInjector()
    abstract fun queueActivity(): QueueActivity

Which module contains this part of code? In QueueComponent You are added ScreenBindingModule::class, but define injector factory in another class - QueeScrennBindingModule::classs.

It's just a typo or it's really two different classes?

Upvotes: 0

Related Questions