Search code examples
javaandroiddependency-injectiondagger-2dagger

Dagger component dependency meaning


I'm experimenting with Dagger 2 and I'm just testing things out to understand the framework.

I'm having a ApplicationComponent that needs to be a singleton for the whole app so I defined it like this:

@Component(modules = {ApplicationModule.class})
@Singleton
public interface ApplicationComponent {
    Context provideContext();
}

With module:

@Module
public class ApplicationModule {

    private Application appContext;

    public ApplicationModule(Application appContext) {
        this.appContext = appContext;
    }

    @Provides
    @Singleton
    public Context provideContext() {
        return appContext;
    }
}

Now I also want a NetworkComponent that needs to be a live as long as the app lives. That network component needs to have a dependency on the ApplicationComponent. So I have my networkcomponent as follows:

@Component(dependencies = {ApplicationComponent.class}, modules = {NetworkModule.class})
@PerApp
public interface NetworkComponent extends ApplicationComponent {
    @Named(DaggerConstants.DEFAULT_RETROFIT)
    Retrofit provideDefault();

    @Named(DaggerConstants.OTHER_RETROFIT)
    Retrofit provideOther();

    void inject(MainActivity activity);
}

Module:

@Module
public class NetworkModule {

    @Named(DaggerConstants.DEFAULT_RETROFIT)
    @PerApp
    @Provides
    Retrofit provideDefaultRetrofit() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.someurl.com/")
                .build();

        return retrofit;
    }

    @Named(DaggerConstants.OTHER_RETROFIT)
    @PerApp
    @Provides
    Retrofit provideOtherRetrofit() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.someotherurl.com/")
                .build();

        return retrofit;
    }

    @PerApp
    @Provides
    SharedPreferences networkPreferences(Context context) {
        return context.getSharedPreferences("network", Context.MODE_PRIVATE);
    }
}

I have some questions:

1) I store the two components in the Application in Android. But to me it seems strange that I store the AppComponent and the NetworkComponent. Is it not better that my ApplicationComponent should provide the NetworkComponent?

2) The annotations @PerApp and stuff does it mean something or is Dagger just looking that there is an Object a live that has the @PerApp annotation and if not then it deletes that? This is not clear to me.

3) Is it something useful to mark a Module with for example @Singleton because it is possible but I don't see that in any example.


Solution

  • I store the two components in the Application in Android. But to me it seems strange that I store the AppComponent and the NetworkComponent. Is it not better that my ApplicationComponent should provide the NetworkComponent?

    You are missing the concept of components. The idea behind the components is to have objects, whose lifetime differs from each other. For example:

    • Object A should be app singleton. Whenever you need this object it would be the exact same object
    • Object B should be activity singleton. Each time your activity destroyed and created a new object would be created.
    • Object C should be fragment singleton. Each time your fragment is attached and detached to activity a new object would be created.

      So you specify, that you want ComponentC to have dependency of ComponentB, which has dependency on ComponentA (Assuming each of them provide the appropriate named dependency.)

    The annotations @PerApp and stuff does it mean something or is Dagger just looking that there is an Object a live that has the @PerApp annotation and if not then it deletes that? This is not clear to me.

    Custom scopes are useful for the objects, who's lifetime you are taking responsibility for. I.e., if you have declared a component with your custom scope, you are responsible for clearing that component, thereafter next time that dependency is asked from component a new object would be created for you.

    In the above example you have to take care of nulling out ComponentB as soon as your activity is being destroyed, otherwise it will provide you the same B object next time you ask for it.

    Is it something useful to mark a Module with for example @Singleton because it is possible but I don't see that in any example.

    It would not make any difference concerning providing dependencies. But maybe it will help you to remember what scope the hosting component has.