Dependency injection in Android – 4. Using Dagger in Android apps

Tram Ho

1. The best practice

If you are familiar with Dagger, we will continue ^^. Here are best practices:

* Use constructor injection with @Inject to add Dagger graphs whenever possible. When it does not:

  • Use @Binds to tell Dagger what interface to implement
  • Use @Provides to tell Dagger how to provide classes that your project doesn’t own

* You should only declare modules once in a component.

* Naming the scope of anotation depends on its usage life cycle. Examples are @ApplicationScope , @LoggedUserScope , and @ActivityScope

2. Adding dependencies

To use Dagger, you add these dependencies to the build.gradle file. The latest version of github dagger can be found

3. Dagger in Android

Consider a sample Android application with the dependency charts below:

In Android you usually create a Dagger diagram in the application layer because you want an instance of the diagram to stay in memory as long as the application is running. In this case the diagram attaches to the application life cycle. For that you will also need the diagram in the application layer. An advantage of this method is that charts are available in the Android Framework classes. Also it simplifies testing by allowing us to use a custom application class in test cases.

Because the interface that creates graphs is annotated with @Component , you can call it ApplicationComponent or ApplicationGraph. We usually keep an instance of that component in our custom application class and call it whenever you need the application diagram, as shown in the following code:

Because some Android framework classes like activity and fragment are system-initiated, Dagger cannot initialize them for us. For specific Activities, any initialization code needs to go into the onCreate () method. That means you can’t use anotation @Inject in the constructor like you did in the previous example. Instead we have to use field injection

Instead of creating dependencies in an Activity required in the onCreate () method, we want Dagger to include those dependencies. For field injection, you apply anotation @Inject to the fields you want to get from the Dagger diagram

For simplicity, the LoginViewModel is not the ViewModel of Architecture Components, it is just a regular class that works like ViewModel.

One of the considerations for Dagger is that the injected fields cannot be private

I would like to introduce the details about injecting Activity, Dagger Modules, Dagger Scopes, Dagger subcomponents. …. Due to some limitations on the time I will update later ^^

4. Best Practices when building a Dagger chart

When building a Dagger chart for your application:

  • When you create a component, you should consider which element is responsible for the component’s life cycle. In this case, the application layer is responsible for ApplicationComponent and LoginActivity is responsible for LoginComponent.
  • Use scope when it makes sense. Abuse of the scope can negatively impact application runtime performance: the object stays in memory as long as the component is in memory and receives a larger scope object. When Dagger provides the object, it uses the DoubleCheck keyword instead of providing factory-type

5. Testing a project when using Dagger

One of the benefits of using Dependency Injection with Dagger is making it easier for us to test.

Unit tests

We don’t have to use Dagger for Unit Tests. When testing a class using constructor injection, you do not need to use Dagger to initialize that class. We can call its constructor directly, directly passing fake or mock dependencies if they are not commented.

End-to-end tests

For integration tests, a good practice is to create a meaningful TestApplicationComponent for testing. Production and testing use a different component configuration.

This requires more modular design than the actual modules in the application. Component testing extends the production component and installs a different set of modules.

FakeNetworkModule has fake implemented the original NetworkModule. There we can provide fake or mock fields of whatever you want to replace.

In integration or end-to-end tests, you will use TestApplication to create TestApplicationComponent instead of ApplicationComponent

This testing application is then used in the custom TestRunner that you will use to run instrumentation tests.

6. Working with Dagger modules

Dagger modules are a way to encapsulate how to provide objects semantically. We can include modules within components but you can include modules inside other modules. This is powerful but also easy to use wrong.

When a module has been added to another component or module, it is already in the Dagger diagram; Dagger can provide objects in that composition. Before adding a module, check that the module must be part of the Dagger diagram by checking if it has been added to the component by compiling the program so that Daggercos can find the necessary dependencies for That module does not.

Good practice indicates that modules should only be declared once in a component

Suppose you have a chart configured this way. ApplicationComponent includes Module1 and Module2 and Module1 includes ModuleX

If now Module2 depends on the classes provided by ModuleX. A bad practice is to include ModuleX in Module2 because ModuleX is included twice in the diagram as seen in the following code:

Instead, one should do one of the following:

  • Reconstruction of the modules and extract the common modules into components.
  • Create a new module with objects that both modules share and extract it into the component

Not restructuring in this way leads to a lot of modules being included with each other without a clear sense of organization and making it harder to see where each dependency comes from.

Good practice (option 1): ModuleX is declared once in the Dagger diagram

Good practice (option 2): Common dependencies from Module1 and Module2 in ModuleX are extracted from a new module called ModuleXCommon that is included in the Component. Then two modules named ModuleXWithModule1Dependencies and ModuleXWithModule2Dependencies are created with dependencies specific to each module. All modules are declared once in the Dagger diagram

7. Conclusion

Through this article, I have basically introduced using Dagger. To complete this article, I have consulted a document from Google Android. Surely there are many shortcomings, I hope to receive contributions from you and will supplement.

Share the news now

Source : Viblo