Sergei Mikhailovskii
Sergei Mikhailovskii

Reputation: 2465

Dagger missing binding while adding AndroidInjector

I have the following problem: I started to study Dagger 2 and trying to add injections to my App class. Here's the code of my App class:

class TraktTvApp : Application(), HasActivityInjector {

    @Inject
    lateinit var androidInjector: AndroidInjector<Activity>

    override fun activityInjector(): AndroidInjector<Activity>? = androidInjector

    override fun onCreate() {
        super.onCreate()

        appContext = applicationContext
        instance = this

        initStetho()
        initFabric()

        DaggerAppComponent
                .builder()
                .application(this)
                .build()
                .inject(this)

        FirebaseInstanceId.getInstance().instanceId
                .addOnCompleteListener(OnCompleteListener { task ->

                    if (!task.isSuccessful) {
                        return@OnCompleteListener
                    }

                    val token = task.result?.token
                }
                )
    }

    private fun initFabric() {
        Fabric.with(this, Crashlytics(), CrashlyticsNdk())
    }

    private fun initStetho() {
        if (BuildConfig.DEBUG) {
            Stetho.initializeWithDefaults(this)
        }
    }

    companion object {
        lateinit var instance: TraktTvApp
        lateinit var appContext: Context
    }

}

In this class I have appContext as Property and I am trying to replace it with injection. For this purpose I added this lines

DaggerAppComponent .builder() .application(this) .build() .inject(this)

When I build my App everything was ok, but when I added

    @Inject
    lateinit var androidInjector: AndroidInjector<Activity>

    override fun activityInjector(): AndroidInjector<Activity>? = androidInjector

And tried to build I got this error:

public abstract interface AppComponent {
                ^
      dagger.android.AndroidInjector<android.app.Activity> is injected at
          com.mikhailovskii.trakttv.TraktTvApp.androidInjector
      com.mikhailovskii.trakttv.TraktTvApp is injected at
          com.mikhailovskii.trakttv.di.AppComponent.inject(com.mikhailovskii.trakttv.TraktTvApp)

I have already seen possible solutions, but none of them helped me. Here's the code of my AppModule:

@Module
class AppModule {

    @Singleton
    @Provides
    fun provideContext(application: TraktTvApp): Context {
        return application.applicationContext
    }

}

And here's AppComponent:

@Singleton
@Component(
        modules = [
            AndroidSupportInjectionModule::class,
            AppModule::class
        ]
)
interface AppComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance

        fun application(application: TraktTvApp): Builder

        fun build():AppComponent

    }

    fun inject(application: TraktTvApp)

}

So, what's the problem and how can I solve it?

Upvotes: 3

Views: 5395

Answers (1)

ysfcyln
ysfcyln

Reputation: 3115

You do not need to add AndroidInjector manually. You can use Dagger base classes so Dagger will handle it for you

You should extend your Application class from DaggerApplication

 class MyApp: DaggerApplication() {

    /**
     * Returns the injector
     */
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {

        val appComponent = DaggerAppComponent.builder().application(this).build()
        appComponent.inject(this)

        return appComponent

    }

Also your Main Component extends AndroidInjector

/**
 * The main component that holds and services all modules within its builder.
 */
@Singleton
@Component(modules = [AndroidSupportInjectionModule::class])
interface AppComponent : AndroidInjector<MyApp> {

    /**
     * A {@see [Component.Builder]} that initializes necessary implementations
     */
    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application : Application) : Builder
        fun build() : AppComponent
    }

}

If you want to use Context, you can add it your AppModule

@Module
class AppModule {

    @Singleton
    @Provides
    fun provideContext(application: Application): Context {
        return application.applicationContext
    }

}

Upvotes: 4

Related Questions