Members injection
The default way for a class to request its dependencies is
via its @Inject
-annotated constructor.
That ensures that the dependencies are present when the object is fully constructed, as is normal Java best practice. There are, however, a few other options.
The @Inject
annotation is also valid on fields and methods. Dagger will set
@Inject
fields after the constructor is invoked. Similarly, it will call
@Inject
methods, supplying the parameters as if they were dependencies
specified in the constructor.
Here’s a simple example:
class Foo {
@Inject Bar bar;
private Baz baz;
@Inject Foo() {}
@Inject
void setBaz(Baz baz) {
this.baz = baz;
}
}
When Dagger creates a Foo
, it will do something like this:
Bar bar = …;
Baz baz = …;
Foo foo = new Foo();
foo.bar = bar;
foo.setBaz(baz);
CONCEPTS
- Field injection is when Dagger sets an
@Inject
-annotated field on a class.- Method injection* is when Dagger calls an
@Inject
-annotated method on a class.- Note that
@Inject
-annotated fields and methods may not beprivate
orstatic
, and fields may not befinal
.
Injecting objects Dagger can’t create
While there are cases where you might want to use field or method injection in
addition to an @Inject
constructor, one reason you might need to use field
or method injection is because Dagger can’t instantiate the class you want to
inject, for example because the class is being instantiated by another
framework.
In this case, you obviously can’t rely on Dagger injecting those fields or methods after it creates the object, because it isn’t creating it.
To solve this problem, Dagger allows you to pass it an instance of a class that
has @Inject
members (fields and methods), and Dagger will set those fields and
call those methods to inject the dependencies the object needs.
There are two ways of doing this in Dagger.
With component methods
One way is to create a method on a component that takes the type you want to
inject as a parameter (and returns void
or its parameter type):
@Component
interface MyComponent {
void inject(Foo foo);
}
…
Foo foo = …;
MyComponent component = DaggerMyComponent.create();
component.inject(foo);
Dagger knows that this isn’t a normal component entry point method because it
doesn’t return anything and it takes a parameter. When you pass a Foo
to the
inject
method in the above example, Dagger will set any @Inject
fields and
call any @Inject
methods on it. And because the inject
method takes a Foo
,
Dagger can confirm at compile time that it will be able to set all of those
fields and call all of those methods with their dependencies.
CONCEPTS
- Members injection methods are
void
methods on a component that take a parameter of a specific type, allowing Dagger to set its@Inject
-annotated fields and call its@Inject
-annotated methods.
MembersInjector
The other way is to use the MembersInjector<T>
type. MembersInjector
has a
single method, void injectMembers(T)
. This method works the same way as a
void
inject method on a component does (described above).
A MembersInjector
can be returned from a component entry point or injected
into a class.
Here’s an example using MembersInjector
:
class MyClass {
private final MembersInjector<Foo> fooInjector;
@Inject
MyClass(MembersInjector<Foo> fooInjector) {
this.fooInjector = fooInjector;
}
void something() {
Foo foo = OtherFramework.getInstance(Foo.class);
fooInjector.injectMembers(foo);
// do stuff with foo
}
}
CONCEPTS
MembersInjector<T>
is a type that Dagger can provide automatically. It has a single method that injects the fields and methods of an object:injectMembers(T)
.