
Author: Konstantin Mars
Senior Developer @ DataArt,
Co-Organizer @ GDG Dnipro
Dependency Injection
What, why and when it is needed
Today we will talk about a tool that helps improve the quality of development for Android. You can solve this problem with Dependency Injection (DI). Usually this term is associated with injections, syringes and a little bit with “dependencies”. In fact, Dependency Injection is a design pattern that provides the implementation of the principle of dependency inversion and implements the rules for creating objects and the independence of implementations.
So, we have a class, the class has a constructor, and there are several class members. When you create an entity of this class, you need to provide the class with instances of the same types that are declared for its class members. In this case, this is the name of the car and the engine type Engine. You will use object references, respectively, the links inside your class will not be empty.
Thus, you implement OOP and can create objects.
Creating classes generates ...
')

- Composition is not inheritance.
- Links will not be empty.
The ability to create objects ...
You can create an object, set the name of the car and create some new engine.

Available to create different objects, for example, the creation of a different type of engine or just another engine.

Suppose you can create two different objects that you will use. In this case, the same engine from the "Patriot". Accordingly, if you put this engine in the Jeep Grand Cheerokee - it will be a bit strange. But, nevertheless, you can do it. This uses the so-called pattern "composition", when the entities that you create will be included in another entity, and this will be, as you see, not inheritance, but composition.

Everything is very simple here: if you look at SuperTunedEngine, you will understand that in fact it is a certain type of heir that has already been declared in advance, and also perhaps an interface implementation - this is not fundamental for us. In this case, the Engine can be an interface.

Looking at the two ads, you see: we can make it so that two objects will depend on some other object. Actually, this is addiction. Thus, the ability to create objects creates dependencies is a rather banal thing.
And ... dependencies
Car depends on Engine. Engines may vary. We'll probably need different engines for testing and production.

As you can see in the diagram (the image is not from our example), the dependencies are very different. You will have dependent services, dependent activity, presenters, view, controllers. All these entities are intertwined with dependencies. If you try to express it graphically, you get about what you see now in the picture.
In a real working system, dependencies will be much larger. Tests that are conducted by well-known companies that provide tools for testing Android applications show that there are thousands of dependencies, even in seemingly simple applications. On average, thousands and tens of thousands of dependencies are found even in the simplest applications. To implement these dependencies as efficiently as possible, without instantiating any other classes within your class each time and without adding a bunch of code that will be repeated and add extra work to you, there is a Dagger tool.
Dagger and JSR-330 Standart
Dagger is based on the JSR-330 standard. This standard has been used by Google for a very long time, and this is the standard for Java Injection.
A bit more non-history
- Dagger 2 - Google, Greg Kick
- Dagger - Square, Jake Wharthon
- Guice - Google, Jesse Wilson
Let's look a little into history: Google once created such a product as Guice (popularly called “Juice”, and in our latitudes - “Goose”). Guice worked with reflection, he followed the annotations, but subsequently the developers from Square improved the system that was in Guice and created Dagger1.
Dagger1 was a cool tool, but, as practice shows, something can be improved here. By the way, Dagger1 also used reflection. And in 2015, developers from Google released Dagger2. It seems that quite recently Jake Wharton (a well-known developer from the company Square) announced its release with an eye on autumn - the promise is fulfilled, we have a high-quality and ahead of competitors in the test results product.
Inversion of Control ( English Inversion of Control, IoC)

Let's return to standards and terminology. So, we have a product that appeared in the course of evolution. It uses JSR-330, which provides a variety of annotations. In addition, it follows certain principles, a kind of development patterns, one of which is Inversion of control (IoC).
The process of providing external dependency to a software component is a specific form of “inversion of control” (IoC), when it is applied to dependency management. In accordance with the principle of single responsibility, the object gives care to build the dependencies required by it to an external, specially designed for this general mechanism.
This thing is related to architectural patterns. We must write the application in such a way that the inner classes associated with the domain logic do not depend on the outer classes, so that the application is written based on the interfaces. Thus, the division of responsibility is realized. Turning to some kind of implementation, we turn, first of all, to the interface
. Inversion of Control is implemented through Dependency Injection, the actual tool is called Dependency Injection (DI).Reflection vs Compile time
Dagger2 uses code generation, unlike Dagger1, which used reflection.
JSR-330
JSR-330 aka javax.inject
- Inject , Qualifier , Scope . etc.
- Standardized Dependency Injection API
- Reference Implementation: Google Guice 2.0
- Also supported by Spring since 3.0
- Defines API, not injector implementation or configuration
JSR describes not only the
Inject annotation, but also provides a whole package of annotations that allow you to declare how entities will interact to provide Dependency Injection.
For example, I’m talking about a specific family of Dependency Injection products that follow this standard. There are other products that do not follow this standard, we will not talk about them today, but they exist. There is
Inject ,
Qualifier ,
Scope - we'll talk about them later. These annotations were not created only for Dagger2, they exist for other injectors, for example, Guice.
So, it's time to add some magic to our code ...

We begin by annotating class members with an
inject annotation. Everything is quite simple. In order to further instantiate these dependencies and our toolkit, Dependency Injection could correctly choose exactly where to instantiate and what, we must also annotate the constructor. Here the situation becomes a bit more interesting.
Notice the default constructor.

The easiest way to provide injection is to create a default constructor. Then inject the default constructor itself and those members that require instantiation of this class to inject. This is done very simply.
Constructor with parameters is a good place for modifications.

In real life, we need constructors with parameters. The system will be able to pick up some of them automatically if they have default constructors. And some, for example, the same Engine, you may have to construct manually.
Also you will inject presenters with the help of such constructors, this is very often used in MVP (Model-View-Presenter).
And yet - how to make it work?

Dagger2.0 injection structure
Injection structure is the interconnection of Dagger components that allow us to combine
inject annotations and combine class declarations.
Components and Modules
Pic. author - Miroslaw Stanek from Azimo
http://frogermcs.imtqy.com/dagger-graph-creation-performance/The Dagger injection structure includes components and modules. If you look at the picture (from the article by Miroslav Stanek from Azima), you will see that the components are containers for modules, and there may be others inside one component. Later we will see that the components that are nested are called subcomponents (@ SubComponent). And we cannot call them simply “components” by the injection rules.
Module - a collection of generators
Module annotation — an annotation that says that this entity — this class — is a module that will generate instances of objects.
Here, too, everything is quite simple. Annotations that generate - this abstract provides. The summary provides simply indicates that this module method will supply you with an entity. The most interesting thing will happen inside this method.
You will need to follow the rules to instantiate the object in some way. Some objects will depend on each other. Some objects will depend on the members of the module class, which you can store in the module. For example, the same context you can put in a module. The module remembers it and then, when instantiating the same agents, you will generate new presenter entities based on the context that the module remembers once it was created.
As you can see, the module has a constructor. In this case, instead of the context, we are passing Application. When creating something new, we can return what is stored in the module itself.
What is a singleton (eng. Singleton)?
When creating some entities, we set certain parameters. Singleton - a statement that says that where the injector
finds the inject annotation, it should not instantiate a new object, but should re-use the already single-time singleton object.
@Component
Component - host for modules, class injector, dependency tree root.

With the component, everything is a little more interesting. The component must take into account the lifetime of the modules that it includes. If we try to use singleton for the component that uses the instantiation lifetime, conflicts will arise. Therefore, you need to clearly understand that, for example, the component for Application will be a singleton, because the object of the Application class exists in a single instance, and there is a lifetime of the application. For activity, for example, this can also be a singleton, and its lifetime will be tied to the lifetime of the activity. If necessary, it is possible to annotate the component with additional annotation
Singleton . There is a list of modules that includes this component.
For example, in Activity there will be an inject annotation. In the component should be specified the modules that make this activity. You must specify in the component where we inject. That is, we have to specify a specific class, and note that it is impossible, for example, to write BaseActivity as a base class, because then injection will occur only in Base aActivity, and in MainActivity, where you need, for example, some Presenter, the rules will be slightly different.

The inject method is a description of who depends. Modules - a description of those who provide dependencies.
Let's go back to the module. The module is declared as a class. It is important to note that the module is a real class that has real references to real objects. And you create it manually when you declare a component, with a bundle. The component, in turn, is the object that Dagger generates. Just at this moment the magic of code generation occurs. Therefore, the component is declared as an interface.
Component initialization generated code used

For example, DaggerAppComponent is initialized inside our application. Note that the generated code used (component initialization) means that we use the generated code. For example, you can detect DaggerAppComponent. As you saw earlier, there was no Dagger prefix. Where did he come from? Yes, Dagger generated the code. He generates it quickly enough. If you accidentally break the injection, which we are talking about (its structure), in the end you will not have a DaggerAppComponent. If you made a small error and incorrectly specified a class, generation will not work - DaggerAppComponent will not appear, and all the magic that provides us to bind our activity and other classes will not work without the generated class. Because the component is the root of the whole tree - this is the basis. And without it, everything else does not work. You should be careful about how we build the injection before, and use the component correctly.
Also note that the component has a builder. Builder - design pattern. We understand that the builder has some arguments that determine how our component will be built on, for example, the AppModule method — an automatically generated method that takes the instance instance class AppModule as an argument. We create the module with our hands and set parameters for it. And call the build method to get the AppComponent. In this link there is an example from the real code:
http://github.com/c-mars/Dagger2Scopes.git .
Inject This! :)

Puttin 'magic will work only after injection ... :)
The Application class has methods that provide access to it. Moreover, this is not a static method, you can simply get a context from get application. You can tackle him to your class - the same thing will turn out and there will be no magic here. But, for what's really important, we will have this getAppComponent.
The idea is that Application stores an AppComponent. We call some additional methods on this component, and then we use the inject method. As you noticed, this one is inject with an indication of the specific class that we declared in the component. In this case, it is the LoginActivity class. You see in the abstract inject, see how we inject dependencies. Magic will work only after injection.
Custom Scopes and efficient memory management
Custom Scopes, as such, serve to provide your lecturing classes with a specific life time.
Object life cycle
Pic. author - Miroslaw Stanek from Azimo
http://frogermcs.imtqy.com/dagger-graph-creation-performanceFor example, you have an activity, and they live for quite a short time, go from one screen to another and kill everything. That is, everything that is injected into the activity can be cleaned up after that, and the application will consume less memory. Some class of user data, for example, User, will live between logins. Application Scope - the most important, root scope, living the longest.
And once again the same matryoshka
Component has a scope of life
Pic. author - Miroslaw Stanek from Azimo
http://frogermcs.imtqy.com/dagger-graph-creation-performance/This mysterious 'plus' ...

Now pay attention to the plus.
Subcomponent declaration

Abstract
Scope allows you to generate scopes of a specific lifetime. For example, ActivityScope will live as long as the activity lives. They annotate components as subcomponents.
But there was a module there!

The data inside is described as in the root component. Except for one thing: when you call plus, pass the module there and instantiate it, you get the subcomponent you need.
Add subcomponent to dependency tree root

What is it used for? For scopes, which can be declared as interfaces, limit the lifetime of our objects.


This type of
Scope will limit the lifetime statically, depending on where you are going to inject. And the other will limit dynamically.
Dynamic means that you will manage it manually, and everything will be removed using the garbage
collector ("garbage collector").
We annotate the component needed by the scopam.
@ActivityScope


@UserScope, for example, how it will work this very scop, which has @Retention (RUNTIME). It can be controlled manually.
@UserScope

To manage it manually, you save the link to the component inside the application next to the AppComponent.

It is created using a special method, an example of code that you can see. Then the code was cleaned, sent to the release, and the garbage
collector removes it. When does this happen? When the user logged out (
“logged out” ). The next time you call another createUserComponent, this component will be created again with other user data.
Finally ... What is injected?
- Modules demo data.
- Presenters.
- Singletons
- Test class implementations.
- ... Everything else that is instantiated and creates dependencies.
In fact, you need to inject something that will help you more effectively inject memory and write code. Presenters must be uniquely used.
Singleton - it is convenient. In the example that I will give now, we injected Mock data for the demo version, and they could also be used with variations for testing.
Home readings
Sample code:
http://github.com/c-mars/Dagger2Scopes.gitI recommend reading Fernando Cejas about design patterns. Miroslav Stanek very well described scopes. He has a wonderful article on how to properly manage @Retention (RUNTIME) and clean memory in time. And, of course, visit the official page Dagger2.
Sense code
How we organized quick agile development using Mock modules and eventually overtook the server side.
The story is. We used Dagger 2 in the project with unit tests, with the correct MVP separation, but the key point was that the server side was not at that time. And we wrote an application that should take the data from the server, show it all beautifully processed by analyzing the data. The main task was to ensure that when REST services appeared, we could quickly switch to them. Quickly do this, you can only change the code manually. With the presence of modules and components, after the appearance of the server, we easily replaced the Mock-data (which was delivered via injection) with real data from the REST API, replacing only one module and one line of code in the declaration of the root component.