Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2 Activity context/ApplicationContext modules

Tags:

dagger-2

I'm struggling with dagger 2 in order to understand how i can pass a context or another according to my needs. - First I have an ApplicationModule annotated @Singleton since it provides hi level objects like the webservice object, the model ..., generally those objects are passed the ApplicationContext (since the y need to live during the whole Application lifetime)

@Singleton
@dagger.Component(modules = {
    AppModule.class
})
public interface AppComponent {
        void inject(MyApp application);
        Model model();
        Context context();<--- should provide the application Context for the Object above (model)
...

the implementation looks like that

@dagger.Module
public class AppModule {

    private final Application app;
    public ApplModule(Application app) {
        this.app = app;
    }

    @Provides
    @Singleton
    Model provideModel(Bus bus) {
        return new Model(bus);
    }

    @Provides
    @Singleton
    Context provideApplicationContext() {
        return app.getApplicationContext();
    }
...
  • secondly I have an Activity Scope componenet in with I provide the current activity and different views which need a Context.

      @ActivityScope
        @Component(
                dependencies = AppComponent.class
                , modules = {ActivityModule.class}
        )
        public interface ActivityComponent {
            void inject(MyActivity activity);
            Context context(); <---should provide the activity's context
            MyView homeView(); <----takes a Context as a contructor parameter
    

    @Module public class ActivityModule { private final Activity activity;

    public ActivityModule(Activity activity) {
    
        this.activity = activity;
    }
    
    @Provides
    @ActivityScope
    public Activity activity() {
        return activity;
    }
    
    
    @Provides
    @ActivityScope
    @Named("viewcontext") <----- if I removed this I get an error from Dagger
    public Context context() {
        return activity;
    }
    
    @Provides
    @ActivityScope
    MyView provideZeView(Bus bus, Model model) { <---- previously receiving the ApplicationContext as a parameter 
        MyView v = new MyView(activity, bus, model); <---- must pass the activity otherwise passing the Context reveived is the ApplicationContext
        return v;
    }
    

    so Here are my questions:

  • I used scopes in order to have a better "granularity" over what is passed and i still get the applicationContext
  • If I remove the @Named qulifier i get an error
  • previously the Views where produced by another module with a dependence to the ActivityModule but still getting the ApplicationContext

Well the point is I am certainly missing something...but I can't figure what, maybe I misundestood the use of Scopes

like image 539
gropapa Avatar asked Aug 08 '15 20:08

gropapa


People also ask

What are Dagger modules?

A Dagger module is a class that is annotated with @Module . There, you can define dependencies with the @Provides annotation. Kotlin Java. // @Module informs Dagger that this class is a Dagger Module. @Module.

Why to use Dagger in Android?

Dagger automatically generates code that mimics the code you would otherwise have hand-written. Because the code is generated at compile time, it's traceable and more performant than other reflection-based solutions such as Guice. Note: Use Hilt for dependency injection on Android.

How do you inject context into a dagger?

You can extend Application class and create static instance of the Application. You can name it e.g. BaseApplication . After that, you can create get() method inside your extended Application class, which will return that instance and will be Application Context at the same time.

What is @component in dagger?

Now Component in a Dagger works by creating a graph of all the dependencies in the project so that it can find out where it should get those dependencies when they are needed. In order to implement this, an interface needs to be created and should be annotated with @Component.


1 Answers

you can use qualifiers like this. in two separate files define the following:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityContext {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext {
}

then in your ActivityModule do this:

@Provides
@ActivityScope
@ActivityContext
public Context context() {
    return activity;
}

and likewise in your appmodule do this:

 @Provides
    @Singleton
@ApplicationContext
    Context provideApplicationContext() {
        return app.getApplicationContext();
    }

now we have a way to ask for whatever type of context we need based on the qualifier @ApplicationContext and @ActivityContext.

so for example in your activity you could do this:

  @Inject @ApplicationContext
    Context c;

which would inject an application context.

and in a module you could do this for example:

  @Provides
    @ActivityScope
    LoginPresenter provideLoginPresenter(@ActivityContext Context context) {
        return new LoginPresenter(context);
    }

to provide an activity context. this is just an example.

like image 189
j2emanue Avatar answered Oct 09 '22 06:10

j2emanue