Search code examples
androiddagger-2dagger

Android Dagger 2.10 to 2.14.1 - Inject Custom Class


I am using Dagger 2.14.1 in my Android application and migrated recently from 2.10. The new version makes it much easier to inject Activities and Fragments, but I can't find a way to inject a custom class where I cannot change the constructor as well. With 2.10 I could write custom inject functions and then use them to simply inject any class:

Simplified Dagger 2.10 Injection with Kotlin:

@Singleton
@Component(dependencies = [], modules = [ApplicationModule::class, ...])
interface ApplicationComponent {

    fun application(): App

    fun inject(authenticationActivity: AuthenticationActivity)

    fun inject(converters: Converters)

    // ...
}

class App : Application() {

    companion object {
        @JvmStatic
        lateinit var component: ApplicationComponent
    }

    override fun onCreate() {
        super.onCreate()
        component = DaggerApplicationComponent.builder()
            .applicationModule(ApplicationModule(this))
            .build()
    }
}
// This class is used by the Room database framwork and I cannot change the constructor and do class Converters @Inject constructor(private val gson: Gson) {
class Converters {

    @Inject
    protected lateinit var gson: Gson

    init {
        App.component.inject(this)
    }

    // ...
}

Simplified Dagger 2.14.1 Injection with Kotlin doesn't provide me with a ApplicationComponent Object to inject my custom classess:

@Singleton
@Component(modules = [ApplicationModule::class, ...])
interface ApplicationComponent : AndroidInjector<App> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<App>()

    fun inject(converters: Converters) // doesn't work!
}

class App : Application(), HasActivityInjector {

    @Inject
    lateinit var activityInjector: DispatchingAndroidInjector<Activity>

    override fun onCreate() {
        super.onCreate()
        // From where do I get my component to call .inject() from another class?
        DaggerApplicationComponent.builder().create(this).inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity> = activityInjector
}

In short: the DaggerApplicationComponent.builder().create(this) returns an AndroidInjector<App!> Object. This Object only has one .inject() functions which only accepts my App Class. So I cannot inject anything else.

Of course there is a lot missing, but I wanted to only post the relevant code. My Dagger 2.14.1 implementation works and all my dependencies in Activities, Fragments and View Models get injected.

I am quite new to Dagger and the more I use it the more I love it, but I couldn't figure out on how to inject custom classes where I cannot change the constructor. Thanks for you help!


Solution

  • Try this:

    class App : Application(), HasActivityInjector {
    
        @Inject
        lateinit var activityInjector: DispatchingAndroidInjector<Activity>
    
        companion object {
            @JvmStatic
            lateinit var instance: App
        }
    
        @Inject
        lateinit var component: ApplicationComponent 
    
        override fun onCreate() {
            super.onCreate()
            instance = this
    
            DaggerApplicationComponent.builder().create(this).inject(this)
        }
    
        override fun activityInjector(): AndroidInjector<Activity> = activityInjector
    }
    

    Then

    object Injector {
        @JvmStatic fun get(): ApplicationComponent = App.instance.component
    }
    

    Now you can do

    class Converters {
    
        @Inject
        protected lateinit var gson: Gson
    
        init {
            Injector.get().inject(this)
        }