Search code examples
androidkotlindagger

"dagger-android" library, how to provide Context(Application)?


It is confusing that all web search results seem to use slightly different versions of Dagger or different approaches. I followed the example which claims that is the better "new way". (https://proandroiddev.com/exploring-the-new-dagger-android-module-9eb6075f1a46) The full sample source code is here (https://github.com/jshvarts/DaggerAndroidKotlinSampleApp).

Now, I want to know how a non-activity/fragment class could be provided with a Context. So, I added a simple class like this,

class Sample2 @Inject constructor (var app: Application)
{
    fun print()
    {
        Log.d("sample2", app.packageName);
    }
}

But even though the sample project had AppModule and AppComponent, the compilation failed, because app could not be provided.

I have searched the web and found this method (https://github.com/google/dagger/issues/832). I followed that code and modified the sample's AppModule and AppComponent like this,

@Module(includes = [AndroidInjectionModule::class])
abstract class AppModule {
    @Binds
    abstract fun application(app: App):Application;

    @Singleton
    @Provides
    fun providesCommonHelloService() = CommonHelloService()
}

@Singleton
@Component(modules = [AndroidInjectionModule::class,
    AppModule::class, ActivitiesModule::class])
interface AppComponent:AndroidInjector<App>
{
    @Component.Builder
    abstract class Builder:AndroidInjector.Builder<App>(){}
}

class App : Application(), HasActivityInjector {
    @Inject
    lateinit var activityInjector: DispatchingAndroidInjector<Activity>

    override fun onCreate()
    {
        super.onCreate()

        DaggerAppComponent.builder().create(this).inject(this)
    }

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

But the, I get the following compilation error.

AppModule.java:7: error: A @Module may not contain both non-static @Provides methods and abstract @Binds or @Multibinds declarations public abstract class AppModule {

Again, as I have said in the beginning, the Dagger examples on the Internet are all slightly different, I do not know how to take two features from two examples.


Solution

  • It is better to separate @Binds and @Provides, you can create a component class:

    @Singleton
    @Component(
        modules = [(AppModule::class)]
    )
    
    interface AppComponent {
        @Component.Builder
        interface Builder {
            @BindsInstance
            fun application(app: Application): Builder
            fun build(): AppComponent
    }
    }
    

    then an AppModule class for all your @Provides

    @Module
    class AppModule() {
       @Singleton
       @Provides
       fun providesCommonHelloService() = CommonHelloService()
    }