Activity Context cannot be provided using Dagger 2
Resolved
I’m new to Dagger 2 and I’m trying to provide an Activity Context for a class without success. I searched a lot but didn’t find any suitable answers.
I can provide application context. But I also need to provide an Activity Context, but I don’t know of any good way to implement it.
I
need to clarify that I’m using Dagger as an Android dependency.
def dagger_version = "2.24"
implementation "com.google.dagger:dagger:$dagger_version"
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
I also only have one AppComponent with the following code:
@Singleton
@Component(
modules = {
AndroidSupportInjectionModule.class,
ActivityBuildersModule.class,
AppModule.class,
ViewModelFactoryModule.class,
}
)
public interface AppComponent extends AndroidInjector<BaseApplication> {
SessionManager sessionManager();
@Component.Builder
interface Builder{
@BindsInstance
Builder application(Application application);
AppComponent build();
}
}
Except that each of my activities has a module, I didn’t find a way to inject the activity context for AppComponent or from ActivityModule.
What is the right thing to do?
Update
I finally found the right way.
First I created a module for the class I wanted to provide
@Module
public class AlertsModule {
@Provides
static Alerts provideAlerts(Activity activity){
return new Alerts(activity);
}
}
Then I go to the ActivityModules I want to inject into that custom class and do a similar binding
@Module
public abstract class MainActivityModule {
...
@Binds
abstract Activity providesActivity(MainActivity activity);
...
}
Finally, I
included CustomClassModule in my ActivityBuildersModule, where I used @ContributesAndroidInjector to provide my activities.
@MainScope
@ContributesAndroidInjector(
modules = {
AlertsModule.class,
}
)
abstract MainActivity contributeMainActivity();
Solution
You can bind a (bind) activity
instance in the same way as the current bind (
bind) application instance by using the @Component.Builder
or @Component.Factory
An example implementation looks like this:
@Subcomponent(...)
interface ActivitySubcomponent {
@Subcomponent.Factory
interface Factory {
ActivitySubcomponent create(@BindsInstance MyActivity activity)
}
}
@Module(subcomponents = [ActivitySubcomponent.class])
class ApplicationModule {
....
}
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
...
((MyApplication) getApplication())
.applicationComponent
.activitySubcomponentFactory()
.create(this)
.inject(this)
}
}