Dependency Injection, a common programming technique, is mainly utilized in Android development to form a good application architecture. With dependency injection, developers can easily reuse code and conveniently refactor and test queries. The best part about dependency injection is that it’s not needed for developing every Android application and can be used per your requirement.
With this in mind, let’s shed some light on the fundamentals of dependency injection and some effective ways to execute it.
Fundamentals of dependency injection
Before we discuss how dependency injection works in Android apps, let’s give a general overview of the concept. For this, you will need to be thorough with classes and how they are used in terms of dependency injection.
Classes generally need references in regards to other classes. For instance, there are two classes: an engine class and a car class. Here, the car class will require an engine to function, like in real life. This is a dependency because it’s impossible for the car to run without an engine.
In this example, we have focused on a single dependency, i.e., an engine. However, in the case of multiple objects, there can be many dependencies like tires, fuel, and more. An engine object is imperative for a car object to operate. And there would be more constructor calls if more objects were required. Now, every time a car will be an object, an engine will become an object, too, as per the example.
Say, ten car objects are made, and ten engine objects are made. What if we could keep one engine object and send it through the constructor function? That’s the perk of using dependency injection. Your memory consumption will be less this way and code complexity as well.
How do classes get objects?
Classes can acquire an object in three ways. They can do so by constructing a dependency, grabbing objects from other places, and by having objects supplied to them.
- The dependency required is constructed by the class.
- Classes can grab objects from other places. A handful of Android APIs like context getters operate in a similar manner.
- Classes can have their objects supplied to them in the form of a parameter. The Android application can offer these objects once the class has been created.
Two Primary Dependency Injection Methods
Developers developing Android applications can facilitate dependency Injection through Constructor injection or Field injection. Here are detailed explanations of the two:
- Constructor Injection: Constructor Injection requires you to pass the various dependencies of specific classes to their respective constructor. We have seen this above in the example.
- Field Injection: Commonly referred to as Setter Injection, this form of dependency injection instantiates dependencies post-class curation. It’s used for classes that the system has instantiated.
Popular Ways To Writing Code in Android App Development
There are three popular ways to write code while developing an Android application. These methods include Hilt, Dagger, and Koin. However, in this section, we will only be focusing on Hilt and Dagger in detail. While Dagger is Dagger 1.0, Hilt refers to Dagger 2.0. Thus both these methods form a merger with each other.
It’s impossible to execute dependency injections without utilizing annotations. Annotations, including the commonly-used ‘Android App’ annotation, are vital in this process. Dependencies are required to be injected into Android classes, which will generate a Hilt component in return.
The component is bound to the lifecycle of the object in the application and offers various dependencies to it accordingly. What’s more? It’s known to be the ‘parent component’ of your application. This means that many components will be able to access dependencies offered by the component.
Hilt is further able to offer dependencies to a multitude of Android classes that possess an entry point annotation. However, this is only possible to execute when an application-level component is present in the application class.
An Android entry point is used for layout files and similar objects, while view-only models Will utilise a Hilt view model and similar annotations depending on the class. Additionally, application, fragment, service, and ViewModel are a few classes Hilt can work with.
Developers generally curate a Dagger graph that becomes more of a permanent part of your application class. Thus the graph is permanently attached to the life of your Android application. There are times when possessing an application context can be useful in a Dagger graph. Additionally, it is imperative for the Dagger graph to be incorporated within the Application class.
Dagger mainly has an upper edge over Hilt because its graph can be available and accessed by other Android framework classes. Testing is also streamlined with Dagger by enabling developers to run custom class Application classes during tests.
Regardless, most prefer using Hilt over Dagger because the annotations present in Hilt are quite more straightforward than Dagger. Additionally, Dagger incorporates grid binds that make the code part a bit more complex comparatively.
We have covered everything you need to know about the fundamentals of dependency injections and the ways to do it in detail above. We have further discussed two ways developers can write code for an Android application. While Dagger and Hilt share a few similarities, Koin is somewhat different from the two.
Therefore, we recommend you try them out for yourself and see which one fits your application requirements best. Hilt is the top preference for many developers compared to the other two, so keep the same in mind while making a decision. Additionally, we have shed some light on the different ways classes acquire objects with examples for the same.
To be more specific, the car and engine example was the simplest to understand how dependency injection works, and constructor injection works. You can use more than one object if you are seeking to create more than one dependency for a class.