What is the purpose of getter methods in components in dagger 2?

I am trying to understand the components in dagger 2. Here is an example:

@Component(modules = { MyModule.class }) public interface MyComponent { void inject(InjectionSite injectionSite); Foo foo(); Bar bar(); } 

I understand what void inject() methods do. But I don’t understand what the other Foo foo() getter methods do. What is the purpose of these other methods?

+7
dependency-injection dagger-2
source share
2 answers

A dagger is a way of connecting diagrams of objects and their dependencies. As an alternative to directly calling constructors, you get instances by requesting them from the dagger, or by providing the object that you would like to input using the instances created by Dagger.

Let me make a coffee house, which depends on Provider<Coffee> and CashRegister. Suppose you are connected to a module (possibly to LightRoastCoffee and DefaultCashRegister implementations).

 public class CoffeeShop { private final Provider<Coffee> coffeeProvider; private final CashRegister register; @Inject public CoffeeShop(Provider<Coffee> coffeeProvider, CashRegister register) { this.coffeeProvider = coffeeProvider; this.register = register; } public void serve(Person person) { cashRegister.takeMoneyFrom(person); person.accept(coffeeProvider.get()); } } 

Now you need to get an instance of this CoffeeShop, but it only has a two-parameter constructor with its dependencies. So how do you do this? Simple: you tell the dagger to make the factory method available on the instance of the component that it generates.

 @Component(modules = {/* ... */}) public interface CoffeeShopComponent { CoffeeShop getCoffeeShop(); void inject(CoffeeService serviceToInject); // to be discussed below } 

When you call getCoffeeShop , Dagger creates a Provider<Coffee> for the LightRoastCoffee delivery, creates a DefaultCashRegister, puts them into the Coffeeshop constructor, and returns the result. Congratulations, you are the proud owner of a fully equipped coffee shop.

Now all this is an alternative to void injection methods, which take an already created instance and inject it into it:

 public class CoffeeService extends SomeFrameworkService { @Inject CoffeeShop coffeeShop; @Override public void initialize() { // Before injection, your coffeeShop field is null. DaggerCoffeeShopComponent.create().inject(this); // Dagger inspects CoffeeService at compile time, so at runtime it can reach // in and set the fields. } @Override public void alternativeInitialize() { // The above is equivalent to this, though: coffeeShop = DaggerCoffeeShopComponent.create().getCoffeeShop(); } } 

So, you have it: two different styles, both of which give you access to completely injected graphs of objects, without listing or caring about which dependencies they need. You may prefer one method or another or prefer factory methods for top-level injections and members for Android or utility applications or any other type of mix and match.

( Note. In addition to using them as entry points into the object graph, no-arg attributes, known as collateral methods, are also useful for displaying bindings for component dependencies, as described in David Rawson in another answer .)

+6
source share

Use in Dependent Components

In the context of a hierarchy of dependent components such as this example , provisioning methods such as Foo foo() are designed to display bindings to the dependent component. "Expose" means "make available" or even "publish." Note that the name of the method itself does not actually matter. Some programmers prefer to call these methods Foo exposeFoo() so that the name of the method reflects its purpose.

Explanation:

When you write a component in dagger 2, you combine modules containing @Provides methods. These @Provides methods can be thought of as “bindings” because they associate an abstraction (such as a type) with a specific way to resolve this type. With this in mind, the Foo foo() methods make a component capable of exposing a binding for Foo to dependent components.

Example:

Let's say Foo is a Singleton application, and we want to use it as a dependency for DependsOnFoo instances, but inside a component with a narrower scope. If we write the naive @Provides method inside one of the MyDependentComponent modules, we will get a new instance. Instead, we can write this:

 @PerFragment @Component(dependencies = {MyComponent.class } modules = { MyDependentModule.class }) public class MyDependentComponent { void inject(MyFragment frag); } 

And the module:

 @Module public class MyDepedentModule { @Provides @PerFragment DependsOnFoo dependsOnFoo(Foo foo) { return new DependsOnFoo(foo); } } 

Assume also that the injection site for DependentComponent contains DependsOnFoo :

 public class MyFragment extends Fragment { @Inject DependsOnFoo dependsOnFoo } 

Note that MyDependentComponent only knows about the MyDependentModule module. Through this module, he knows that he can provide DependsOnFoo instance of Foo , but he does not know how to provide Foo on its own. This happens despite the fact that MyDependentComponent is a dependent component of MyComponent . The Foo foo() method in MyComponent allows the dependent component MyDependentComponent use the MyComponent binding for Foo to enter DependsOnFoo . Without this method, Foo foo() compilation will fail.

Use to resolve binding

Say we would like to get Foo instances without invoking inject(this) . The Foo foo() method inside the component will allow this in much the same way that you can call getInstance() using Guice Injector or Castle Windsor Resolve . The illustration is below:

 public void fooConsumer() { DaggerMyComponent component = DaggerMyComponent.builder.build(); Foo foo = component.foo(); } 
+6
source share

All Articles