Java – Use the (external) DI container (Dagger 1) for proper dependency injection in Android

Use the (external) DI container (Dagger 1) for proper dependency injection in Android… here is a solution to the problem.

Use the (external) DI container (Dagger 1) for proper dependency injection in Android

I’m currently developing (actually building) an Android app with Bluetooth connectivity and HTTP communication and RESTful services. I happened to come across a “inject” framework called Dagger, which was very revolutionary for me. However, I started thinking more about the “true spirit” of dependency injection and came across more blog posts/opinion-patterns that explained the concept and actually suggested using “constructor injection” and marking others (field and setter injections) as “inject”. ”

I do understand their concerns about field and setter injection via the DI framework, since the former doesn’t explicitly reveal an object’s dependencies, and the latter doesn’t strictly “require” dependencies. However, there is some strong opinion that the only valid, useful, and truly object-oriented form of dependency injection is constructor injection.

I’m particularly worried about Android. Developing an Android application means dealing with a lot of activities, services, fragments, broadcast receivers, etc., many of which don’t let us handle constructors. To provide dependencies using the DI container (Dagger), I just need to use field injection for the dependencies. Why not use a POJO factory? The only advantage of using the DI framework for field injection seems to be the ability to provide separate modules (one for production and one for inject mock objects for testing), but I don’t know if it’s worth the performance overhead, if any.

For now, in my strictly limited view, the only advantage of using Dagger is to reduce the amount of code to write and avoid the hassle of connecting objects to properly pass dependencies.

So I’m coming to the conclusion that I may have completely misunderstood the concept of dependency injection (inject), or/and that I missed the right way to use Dagger, or/and maybe I’m too opinionated (or just less capable) in object-oriented design.

Please educate me on proper use of DI containers and lack of insight/understanding!

Solution

TL;DR: Not having to deal with wiring classes together is a huge advantage, and not having to rewire during refactoring is an even greater advantage.

I find that your “only advantage” is still a huge advantage. IMHO, when you add or refactor existing code, the most valuable part of DI comes in. I often come across situations where something at the “leaf” of the dependent graph needs something extra at the root of the graph (i.e. UserStorageHelper needs context). Without DI, it is necessary to pass the object through onCreate/onAttach between each layer of the constructor and/or some root and target dependencies. DI will allow you to add that dependency with minimal refactoring cost. IMO, which makes the code easier to understand because at every level, you can check and say “this object needs some dependencies”. Any child dependencies that these objects have are not immediately useful information, but you can easily check them as well. (If you want an overview, Dagger also generates dependency graphs, which I think is pretty concise.) )

In contrast, changing the dependencies of a “leaf” object can cause ripple effects on the graph that are not immediately apparent. However, when you need to modify every constructor in the dependency graph, I usually find fixing DI issues better than potentially refactoring at scale.

Regarding the proposal to switch to POJO factories, it seems to me that you still have the same dependency problem. Each layer of a factory requires another factory to get its dependencies. Writing it yourself seems just as tedious, so you can generate it from code, but right now you basically only have a provider for dagger.

In addition to providing different implementations in my tests, I use it extensively to handle build styles/dimensions/build types (injecting different types of logger modules?). No operation with real advertising module? )。

Ultimately, practicality depends entirely on your project. Dagger/DI is useful in many situations, but not in all cases. Kind of like a multitool, you can use it in a number of different ways. Sometimes it’s overkill (you just need a Screwdriver, not a bottle opener), and sometimes it doesn’t solve your problem at all (it can’t be a good hammer no matter how hard you try). The only caveat is that adding DI later is much more difficult than using it from the start, so I tend to add it as an overkill option at the beginning of a project, rather than going into a project and hoping I already have it.

Related Problems and Solutions