Introduction To Libraries And Dependencies In Android
Libraries and dependencies in android intro:
Case study: Android applications built with java
Introduction:
Every time we code an android application, we at some point have to import certain libraries and add them as dependencies in our android studio project. These libraries help us implement with ease certain features, functionalities, binding’s etc. which forms the base logic of our mobile application. Mobile apps generally rely on these libraries to function as intended hence they are called dependencies.
So what are libraries and dependencies? Libraries and dependencies are relatively the same, Library is a dependency. Dependency means things that your app depends on. Dependency can be a module, library or a file.

In Android Studio, dependencies allows us to include external library or local jar files or other library modules in our Android project. Say for example: Suppose I want to show some images in ImageView. But I’m using Glide Library to enhance the smoothness of application. So I have to add a dependency in the build.gradle(Module App) as:
compile 'com.github.bumptech.glide:glide:3.7.0'
Now I can use Glide library and show my images because after syncing the project gradle automatically imports the library into my project.
Dependency Injection: Dependency injection is a widely used technique in software engineering and is used to eliminate the coupling of code.
Let’s look at this simple code:
class Car{
private val engine = Engine()
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.start()
}

We have a class car that constructs an object engine, in this case engine is a dependency for car. That means engine is needed to construct car. In this code above we are not using any dependency injection technique as you can see the class car itself is constructing engine.
Problems with this approach:
- Car and Engine are tightly coupled
- Car is constructing its own engine hence using different engine implementation is not easily possible
- Testing is difficult as using a test double Engine for different use cases is not possible.
A simple solution: instead of car to construct its own engine, we are passing the engine as a constructor parameter. Now car and engine are not tightly coupled as we are getting the engine from outside the car. This approach will solve all the problems listed above.
Advantages of dependency Injection approach:
- Car can easily be reused, as we can easily pass implementations of engine while constructing the car.
- Testing becomes easy, as now we can pass test doubles for testing car.
Two main types of Dependency Injection: there are two widely used types of dependency injection
- Constructor injection
- Field injection
Constructor injection: Siting the code snippet below we see how constructor injection works, this is the also the same for field injection. This approach can also be called manual dependency injection.

class Car (private val engine: Engine){
fun start() {
engine.start()
}
}
fun main(args: Array) {
val engine = Engine()
val car = Car(engine)
car.start()
}
Field injection: in both approaches car is not constructing its own engine, but the engine is being injected into the car.
class Car{
lateinit var engine: Engine
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.engine = Engine()
car.start()
}
Problems with Manual Dependency Injection:
- It generates a lot of boiler plate code.
- Managing lifecycles of dependencies in memory can be a tedious task.
Automated Dependency Injection: This solution can be categorized into two types:
- Reflection Based solution which generates code in run-time.
- Static solution which generates code in compile time.
Recommended Dependency Injection for Android:
- Dagger2
- Hilt
In later topics we will be discussing how to implement different dependencies in our android studio projects.
leave your comment