Search code examples
androidkotlindependency-injectiondagger-2

Android dagger2 , some things not clear


I'm learning dagger2 with a module architecture. And I think, something is not clear to me, for example

in module utilites i have di package

class UtilsComponent

@Component(modules = [UtilsModule::class])
interface UtilsComponent {

    fun getResourceProvider() : IResourceProvider
    fun getNetworkProvider(): INetworkProvider

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): UtilsComponent.Builder
        fun build(): UtilsComponent
    }
}

@Module
abstract class UtilsModule {

    @Binds
    abstract fun bindContext(application: Application): Context

    @Module
    companion object {
        @Provides
        @JvmStatic
        fun bindResourceProvider(context: Context): IResourceProvider {
            return ResourceProvider(context = context)
        }

        @Provides
        @JvmStatic
        fun bindNetworkProvider(context: Context): INetworkProvider {
            return NetworkProvider(context = context)
        }
    }
}

then in app package in AppComponent i included all modules

@Component(
            dependencies = [UtilsComponent::class],
            modules = [
                    AndroidInjectionModule::class,
                    ActivityBindingModule::class,
                    MainModule::class // test module
            ]
)

@AppScope
interface AppComponent: AndroidInjector<App> {
    // inject to ...
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): AppComponent.Builder

        fun utilsComponent(utilsComponent: UtilsComponent): AppComponent.Builder

        fun build(): AppComponent
    }

}

In the app component, I have MainModule - this is my test module, so this module looks like this

@Module
class MainModule {

    @Provides
    fun getMainPresenter(networkProvider: NetworkProvider): MainPresenter {
        return MainPresenter(networkProvider)
    }

}

when I run the app, I have an error

 [Dagger/MissingBinding] com.example.utilities.di.UtilsModule cannot be
 provided without an @Provides-annotated method. public abstract
 interface AppComponent extends
 dagger.android.AndroidInjector<com.example.testmoduleapp.App> {
                 ^
       com.example.utilities.di.UtilsModule is injected at
           com.example.testmoduleapp.di.modules.MainModule.getMainPresenter(utilsModule)
       com.example.testmoduleapp.ui.activities.main.MainPresenter is injected at
           com.example.testmoduleapp.ui.activities.main.MainActivity.mainPresenter
       com.example.testmoduleapp.ui.activities.main.MainActivity is injected at
           dagger.android.AndroidInjector.inject(T) [com.example.testmoduleapp.di.AppComponent →
 com.example.testmoduleapp.di.modules.ActivityBindingModule_MainActivity.MainActivitySubcomponent]

I understand that the error is because I have not a module witch return NetworkProvider object, but I can't understand how I can get this object from UtilsModule

also in App

@Inject
    lateinit var androidInjector : DispatchingAndroidInjector<Any>
    override fun androidInjector(): AndroidInjector<Any> = androidInjector

    companion object{
        lateinit var appComponent: AppComponent
    }

    override fun onCreate() {
        super.onCreate()
        initializeDagger()
    }

    private fun initializeDagger() {
        appComponent = DaggerAppComponent
            .builder()
            .application(this)
            .utilsComponent(provideUtilsComponent())
            .build()
    }

    private fun provideUtilsComponent(): UtilsComponent {
        return DaggerUtilsComponent
            .builder()
            .application(this)
            .build()
    }

Solution

  • In Dependencies Graph You already provide INetworkProvider so when you need NetworkProvider it means Dagger can not be resolved. Change to this, don't forget to change constructor MainPresenter to INetworkProvider

        @Provides
        fun getMainPresenter(networkProvider: INetworkProvider): MainPresenter {
            return MainPresenter(networkProvider)
        }
    

    but i cant understand how i can get this object from UtilsModule

    For your question, in UtilComponent you already exposed getNetworkProvider() it means any Componenent dependencies to UtilsComponent can be get it.