Reputation: 43
SOLVED
I am new with Dagger 2 and I am trying to provide Activity Context to classes but without success. I search a lot but did not find any appropriate answer.
I can provide Application Context. But I also need to provide Activity Context as well and I don't know any good way to implement that.
I need to clarify that I am using Dagger for Android dependencies.
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 have only an 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 I have a module for each of my activity but I didn't find a way to inject the Activity Context either for AppComponent or from a ActivityModule.
What is the right way to do that?
UPDATE
I finally found the right way to do that.
First I created a module for the class that I want to provide
@Module
public class AlertsModule {
@Provides
static Alerts provideAlerts(Activity activity){
return new Alerts(activity);
}
}
Then I go to the ActivityModules that I want to Inject that custom Class and do a Binding like that
@Module
public abstract class MainActivityModule {
...
@Binds
abstract Activity providesActivity(MainActivity activity);
...
}
And finally I just include the CustomClassModule in my ActivityBuildersModule where I use @ContributesAndroidInjector to provide my Activities.
@MainScope
@ContributesAndroidInjector(
modules = {
AlertsModule.class,
}
)
abstract MainActivity contributeMainActivity();
Upvotes: 3
Views: 2162
Reputation: 2731
You can bind an instance of Activity
in the same way you're currently binding an instance of Application
, either by using an @Component.Builder
or an @Component.Factory
.
An example implementation would look something 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)
}
}
Upvotes: 4
Reputation: 61
@Named annotation helps us to differentiate the Context. We can differentiate the method context() in ActivityModule and ContextModule by adding the @Named annotation as below:
@Module
public class ActivityModule {
private final Context context;
ActivityModule(Activity context){
this.context = context;
}
@Named("activity_context")
@Provides
public Context context(){ return context; }
}
@Module
public class ContextModule {
private final Context context;
ActivityModule(Activity context){
this.context = context;
}
@Named("application_context")
@Provides
public Context context(){ return context.getApplicationContext(); }
Then, we tell Dagger to use the respective Context, as below:
@Module(includes = ContextModule.class)
public class OkHttpClientModule {
....
@Provides
public File file(@Named("application_context") Context context){
File file = new File(context.getCacheDir(), "HttpCache");
file.mkdirs();
return file;
}
....
}
Hope this helps.
Upvotes: 0
Reputation: 6035
@Module
class MainActivityModule(mActivity: MainActivity) {
var mActivity: MainActivity
init {
this.mActivity= mActivity
}
@Singleton
@Provides
fun getMainActivity(): MainActivity{
return mActivity
}
}
now add this module to your Component class and pass your activity to module constructor while using your component builder hope this may helps you.
Upvotes: 0