Do you have a specific package where you put all the Dagger related classes?
Or do you put them next to the relevant class they inject, e.g. if you have an MainActivityModule
and MainActivityComponent
, you put them in the same package as your MainActivity
.
Also, I've seen quite a few people defining components as inner classes, e.g. an ApplicationComponent
that is defined inside the Application
class. Do you think this is a good practice?
I don't have much experience with that, but I can show you my approach. Maybe some people with more experience can improve that solution or provide their point of view.
I usually organize Dagger 2 classes like that:
di
package contains classes related with Dagger 2 and dependency injection.ApplicationComponent
- I haven't created an Android application with many Dagger 2 components yet and I've seen solutions with only one component.modules
package contains Dagger 2 modulesI don't create module per Activity. Modules group specific functionality. E.g. elements strongly connected with system like interface for SharedPreferences, EventBus (if you are using something like that), network connectivity, etc. may be located in
AndroidModule
. If your project has important interfaces for WebService or there's a lot of them, you can group them inWebServiceModule
. If your application is for example responsible for analyzing network and has many interfaces for similar tasks related to the network, you can group these interfaces inNetworkModule
. When your application is simple, it may happen that you will have only one module. When it's complicated, you can have many modules. In my opinion, you shouldn't have many interfaces in a single module. When there's such situation you may consider splitting them into separate modules. You can also keep some business logic specific for your project in a separate module.I'm not sure if it's a good or bad practice. I think there's no need to do that. You can create public static
get()
method inside class extendingApplication
class, which will return instance ofApplication
as a singleton. It's much simpler solution and we should have only one instance of anApplication
class. If we want to to mock Context in a unit tests, we can accept Context as a parameter and in an application code, pass Application Context or Activity Context depending on the situation.Please note, it's just my approach and some more experienced developers may organize their projects in a different and better way.
EDIT: Let me start out with the fact that this is close to the truth here, but this is an antipattern as described by Martin Fowler's
Data Domain Presentation Layering
article HERE (CLICK THE LINK!), which specifies that you shouldn't have aMapperModule
and aPresenterModule
, you should have aGalleryModule
and aSomeFeatureModule
which has all the mappers, presenters etc. in it.The smart route to go about it is to use component dependencies to subscope your original singleton component for each feature you have. This what I described is the "full-stack" layering, separation by features.
The one written down below is the "anti-pattern", where you cut your application's top level modules into "layers". It has numerous disadvantages to do so. Don't do it. But you can read it and learn what not to do.
ORIGINAL TEXT:
Normally, you'd use a single
Component
like anApplicationComponent
to contain all singleton dependencies that you use throughout the app as long as the entire application exists. You would instantiate this in your Application class, and make this accessible from elsewhere.Project structure for me currently is:
For example, mine is like this:
And you need an
ApplicationComponent
that can inject into whatever package-protected fields of whatever class you want to field-inject to.For me,
AppContextComponent
would be a@Subcomponent
, but that is not actually what it means. Those are just a way to create a subscope, and not a way to cut your component into smaller parts. So the interface I inherit is actually just a normalinterface
with provision methods. Same for the others.Component dependencies (which allows you to subscope, just like subcomponents) don't allow multiple scoped components, which also means your modules would be unscoped. This is due to how you cannot inherit from multiple scopes, just like you can't inherit from multiple classes in Java.
Unscoped providers make it so that the module does not retain a single instance but a new one on every inject call. To get scoped dependencies, you need to provide the scope on the module provider methods too.
In an application, if you use Singleton components everywhere, you won't need more components, unless you create subscopes. If you want, you can even consider making your modules a complete data provider for your views and presenters.
Subscoping allows you to have multiple instances of your presenter, which can then store state. This makes sense in for example Mortar/Flow, where each screen has its own "path", and each path has its own component - to provide the data as a "blueprint".