This is a Canonical Question because there are a lot of misconceptions about object initialization with Dagger 2.
If your question was flagged as a duplicate please read this post carefully and make sure to understand the difference between constructor injection and field injection.
I try to inject a Context
into my presenter, but I get a NullPointerException when trying to use it.
class MyPresenter {
@Inject Context context;
private MyView view;
@Inject
MyPresenter(MyView view) {
this.view = view;
}
}
My module looks like this
@Module
class MyModule {
@Provides
MyPresenter provideMyPresenter(MyView view) {
return new MyPresenter(view);
}
}
I inject the presenter in my Activity here:
class MyActivity extends Activity {
@Inject MyPresenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
createMyActivityComponent().inject(this);
}
}
The above includes both constructor and field injection, but neither done right. The example would behave the same if we removed all the
@Inject
annotations fromMyPresenter
since we're not using any of them.Make sure to use either constructor injection or field injection. Mixing both will usually indicate an error in your setup or understanding.
@Inject
on a field is a marker for field injection@Inject
on a constructor is a marker for constructor injectionThis means your class should have either of
@Inject
on the constructor, or@Inject
on all the fields to initialize, but none on the constructor!Don't sprinkle
@Inject
everywhere and expect things to work! Make sure to place the annotation where needed. Don't mix field and constructor injection!Constructor injection should be favored over field injection as it creates an initialized and usable object. Field injection is to be used with Framework components where the Framework creates the objects. You have to manually call
component.inject(object)
for field injection to be performed, or any annotated fields will be null when you try to use them.Constructor Injection
As the name suggests you put your dependencies as parameters in the constructor. The annotation on the constructor tells Dagger about the object and it can then create the object for you by calling it with all the required dependencies. Dagger will also inject any annotated fields or methods after creating the object, but plain constructor injection should usually be favored as it doesn't hide any dependencies.
Dagger creating the object also means there is no need for a
@Provides
method in your module that creates the object. All you need to do is add@Inject
to the constructor and declare the dependencies.If you want to bind your implementation to an interface, there is still no need to create the object yourself.
And there is even a shorter (and more performant) version of the above use-case:
Constructor injection should be your default way of using Dagger. Make sure that you don't call
new
yourself or you misunderstood the concept.Field Injection
There are times when you can't use constructor injection, e.g. an Activity in Android gets created by the Framework and you shouldn't override the constructor. In this case we can use field injection.
To use field injection you annotate all the fields that you want initialized with
@Inject
and add avoid inject(MyActivity activity)
method to the component that should handle the injection.And somewhere in your code you have to call
component.inject(myActivity)
or the fields will not be initialized. e.g. inonCreate(..)
Field injection is not transitive. Just because you inject an Activity this does not mean that Dagger will also inject the fields of the presenter it injected. You have to inject every object manually, which is one reason why you should favor constructor injection.
There are tools that help mitigate the boilerplate of creating components and injecting your objects like
AndroidInjection.inject()
which will do this for you, but it still has to be done. Another example isAppInjector
which adds various lifecycle listeners to inject your Activities and Fragments, but it will still callAndroidInjection
which then creates your component and injects the object.Make sure that you inject the object before using it and that there is no constructor annotated with
@Inject
to avoid confusion.What else?
There is also the lesser used method injection and of course Dagger can't inject third party libraries, which you have to construct and provide in your modules.
Remove @Inject from the Context and create a separate module for providing Context dependency
then create your DaggerComponent. (I have created it in Application class and this refers to ApplicationContext
You can skip .MyModule() if you want because unlike Context module it has no external dependency.