Dagger 2 Injecting Constructors

﹥>﹥吖頭↗ 提交于 2019-11-29 20:27:16
David Medenjak

When I call injectBaseActivity(this) it "tells" dagger that all @Inject annotations are dependencies of my class, and then it searches my project for @Inject annotated constructors that matches that type?

Exactly. But it's not done when you call injectBaseActivity, but it all happens during compile time. This is one way of annotation processing (another makes use of reflection at runtime).

When you build your project the dagger-annotation-processor you include (as a dependency)in your build.gradle file gets called with a list of all your fields, classes, etc annotated by the @Inject annotation and builds a dependency graph with it. It then resolves the graph, generating source code that provides all the dependencies for the items on the graph.

injectBaseActivity just executes the code which was generated before, and assigns all the dependencies to your object. It is proper source code, which you can read, and debug.

The reason this is a compile step—simply put—is performance and validation. (e.g. If you have some dependency cycle, you get a compile error)


how does dagger knows that my AuthControllers is a dependency for BaseActivity?

@Inject
AuthController authController;

By annotating the field @Inject dagger knows you want an AuthController. So far so good. Now dagger will look for some means to provide the controller, looking for it within the component, the components dependencies, and the components modules. It will also look whether the class can be supplied on its own, because it knows about its constructor.

How does dagger know about the objects constructor if you don't include it in any module?

@Inject
public AuthController(Context context) { /**/ }

By annotating the constructor with inject you also told dagger that there is a class called AuthController and you need a context for it to be instantiated. It is basically the same as adding it to your module.

A module @Provides method should be used if you don't have the source code to just add the @Inject annotation to the constructor, or if the object needs further initialization. Or in your case...

[...]the Module files could be used as a "documentation" of my dependencies tree [...]

Yes, of course you could do that. But as your project grows you will have to maintain a lot of unnecessary code, since the same could have been done with a simple annotation on the constructor.

Is there any best practices for when using @Inject annotations in constructors or when to add the @Provides method in Modules files?

If you want to provide different versions for a different context (e.g. implementing an interface in 2 different ways) there is also the @Binds annotation that tells dagger which class you wish to provide as implementation.

Other than that I believe you should always use constructor injection when possible. If something changes you don't have to touch any other parts of your code, and it is just less code that you write, and hence less places where you could include a bug.

Also Dagger can and does optimize a lot by knowing more, and if you implement unnecessary code it will have to work with the overhead you introduced


Of course in the end it is all up to what you think is best. After all it is you that has to work with your code ;)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!