简体   繁体   中英

Dagger2 - when to exposing objects in component vs providing them in a module file -

Im not clear in Dagger2 on when to put objects themselves exposed in a component... Lets take a look at a normal way I have provided dependencies:

@Module
public class NetworkModule {

    private static final String NAME_BASE_URL = "_BASE_URL";

    @Provides
    @Named(NAME_BASE_URL)
    String provideBaseUrlString() {
        return "http://www.pomelo.baseURL.com";//Constants.BASE_URL;
    }

    @Provides
    @Singleton
    Converter.Factory provideGsonConverter() {
        return GsonConverterFactory.create();
    }


    @Provides
    @Singleton
    Retrofit provideRetrofit(Converter.Factory converter, @Named(NAME_BASE_URL) String baseUrl) {

        return new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(converter)
                .build();
    }}

Then I'd have an AppComponent where I would declare that this module is tied to that AppComponent and I would also declare any classes that want to be injected by it like this:

@Singleton
@Component(modules = { NetworkModule.class})
public interface AppComponent {

    void inject(MyActivity target);
}

But I have seen this the following as well. Lets take the retrofit dependency as an example:

@Singleton
@Component(modules = { NetworkModule.class})
public interface AppComponent {
    Retrofit retrofit(); //what does it mean to define an object here ?
}

What does it mean when you put an object itself in the component? Do I still need a provides method in the network module? What am I declaring when I do this?

What am I declaring when I do this?

Components can expose dependencies by this getter like structure:

@Component
public interface AppComponent {
  Retrofit retrofit(); // expose Retrofit
}

What this does is simply put provide you with a getter, or a provision method to be exacct.

If you want to fetch a dependency yourself, you can just call

Retrofit retrofit = appComponent.retrofit()

and Dagger will create / pass you the object.

Do I still need a provides method in the network module?

Of course. This is nothing but an interface declaring that your component can provide others with Retrofit . Dagger will just implement the interface, and if there is no way to provide the object, you will get the probably all to well known compile error cannot be provided without a @Provides...

So yes, the component still needs access to the object, whether this happens with constructor injection, from a module, a parent component, or a dependency.


So why do you need this?

There might be a case where you need some access to objects, but can't or won't inject your dependencies. You could use

@Component
public interface MyComponent {
  Provider<SomeThing> someThing();
}

to expose a provider to create objects of type SomeThing . This might be useful if you plan on creating some sort of factory, where you let Dagger create and initialize the components for you.

The more common approach is within Dagger itself, just have a look at component dependencies :

As an alternative [to subcomponents], components can use bindings only from another component interface by declaring a component dependency.

If you use @Component(dependencies=SomeOtherComponent.class) only those objects declared like above can be accessed by the dependent component and if you remove the provision method from the interface any dependent component won't have access to it anymore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM