Skip to content Skip to sidebar Skip to footer

How To Provide Context With Dagger2

I am learning Android and I am following some guides for Retrofit2 with RxJava and Dagger2. Now I want to handle no internet connection case. I've found this answer, which seems to

Solution 1:

You can use the @Provides annotation in your DaggerModule to obtain application Context. Alternatively you can create a module which accepts a Context parameter in its constructor in case you need activity context. Then you can build the component in your activity and inject the arguments into it.

@ModulepublicclassAppModule {

    private Context context;

    publicAppModule(@NonNull Context context) {
        this.context = context;
    }

    @Singleton@Provides@NonNullpublic Context provideContext(){
        return context;
    }

}

Application class:

publicclassPFApplicationextendsApplication {

    privatestaticAppComponent appComponent;

    publicstaticAppComponentgetAppComponent() {
        return appComponent;
    }

    @OverridepublicvoidonCreate() {
        super.onCreate();
        appComponent = buildComponent();
    }

    publicAppComponentbuildComponent(){
        returnDaggerAppComponent.builder()
                .appModule(newAppModule(this))
                .build();
    }
}

Solution 2:

Just wanted to supplement @anton-kazakov's answer, to provide a way to supply activity/service context in addition to application context:

ApplicationContext

import javax.inject.Qualifier;

@Qualifierpublic@interface ApplicationContext {
}

ServiceScope

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.inject.Scope;

@Scope@Retention(RetentionPolicy.RUNTIME)public@interface ServiceScope {
}

ApplicationModule

@ModulepublicclassApplicationModule {

    private MyApplication mMyApplication;

    publicApplicationModule(@NonNull MyApplication myApplication) {
        mMyApplication = myApplication;
    }

    @Singleton@Provides@NonNull@ApplicationContextpublic Context provideApplicationContext() {
        return mMyApplication;
    }
}

ServiceModule (or, activity etc.)

import dagger.Module;
import dagger.Provides;

@ModulepublicclassServiceModule {

    privatefinal MyService mMyService;

    publicServiceModule(MyService myService) {
        mMyService = myService;
    }

    @ServiceScope@Providespublic Context provideContext() {
        return mMyService;
    }
}

ApplicationComponent

import javax.inject.Singleton;

import dagger.Component;

@Singleton@Component(modules = {ApplicationModule.class})publicinterfaceApplicationComponent {

    ServiceComponent newMyServiceComponent(ServiceModule serviceModule);

    // This is optional, just putting here to show one possibilityvoidinject(BootCompleteReceiver bootCompleteReceiver);

}

ServiceComponent

import dagger.Subcomponent;

@ServiceScope@Subcomponent(modules = {ServiceModule.class})publicinterfaceServiceComponent {

    voidinject(MyService myService);

}

Application

publicclassMyApplicationextendsApplication {

    privateApplicationComponent mApplicationComponent;

    @OverridepublicvoidonCreate() {
        // mApplicationComponent = DaggerApplicationModule.builder()//         .applicationModule(new ApplicationModule(this))//         .build();super.onCreate();
    }

    /**
     * Note: {@link ContentProvider#onCreate} is called before 
     * {@link Application#onCreate}, hence if you have a 
     * {@link ContentProvider}, inject here instead of 
     * in {@link Application#onCreate}.
     * <p>
     * https://stackoverflow.com/a/44413873
     * <p>
     * https://stackoverflow.com/questions/9873669/how-do-i-catch-content-provider-initialize
     *
     * @param base The base Context.
     */@OverrideprotectedvoidattachBaseContext(Context base) {
        super.attachBaseContext(base);
        mApplicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(newApplicationModule(this))
                .build();
    }

    publicApplicationComponentgetApplicationComponent() {
        return mApplicationComponent;
    }
}

Service

import javax.inject.Inject;

publicclassMyServiceextendsService {

    @OverridepublicvoidonCreate() {
        ((MyApplication) getApplicationContext())
                .getApplicationComponent()
                .newMyServiceComponent(newServiceModule(this))
                .inject(this);
        super.onCreate();
    }
}

References

https://dagger.dev/api/2.19/dagger/Component.htmlhttps://dagger.dev/api/2.19/dagger/Module.html#subcomponents--

Solution 3:

Kotlin approach

You can provide the Application, which can be used to provide the `Context.

Define an AppComponent:

import android.app.Application
import dagger.BindsInstance
import dagger.Component
import javax.inject.Singleton

@Component@SingletoninterfaceAppComponent{
  @Component.Builder
  interfaceBuilder{
    funbuild(): AppComponent

    @BindsInstancefunapplication(application: Application): Builder
  }
}

Extend Application like so:

abstractclassMyApp : Application() {
    overridefunonCreate() {
       super.onCreate()
       DaggerAppComponent.builder().application(this).build()
       // ..
    }
}

Post a Comment for "How To Provide Context With Dagger2"