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"