Below are widely used Dependency Injection frameworks mostly by android & Java application projects.
For Android application development, the suggested Framework by Google are Dagger and Hilt. These frameworks help to avoid writing boilerplate code.
Guice
With 10K stars this framework is mostly used by Java developers where Java is used for backend & Application development.
For Android, this framework is not suggested as this framework use reflections to scan annotations from code. This requires significant CPU cycles and RAM thus slowdowns application launch.
Reflection on the desktop/server JVM is very efficient, and even very large Guice applications don’t have performance problems related to Guice.
Manage your app’s memory | Android Developers : Other dependency injection frameworks that use reflection tend to initialize processes by scanning your code for annotations. This process can require significantly more CPU cycles and RAM and can cause a noticeable lag when the app launches.
Dagger
Dagger is an open source Guice alternative designed to run efficiently on Android.
No doubt, Dagger makes life easier, for Android Library development this seems to cause issue if Application include library that use different version of Dagger. (Note: Gradle use latest version of library if library has multiple versions in Application.)
Dagger is a fully static, compile-time dependency injection framework for Java, Kotlin, and Android. The dependency of Dagger is not included to .aar for Android Library.
listed issue:
android - Dagger 2. Library and app has different version Compilation issues after moving to 2.34 from 2.33 - Hilt · Issue #2541 · google/dagger
Hilt (Beta)
Hilt is built on top of the popular DI library Dagger to benefit from the compile-time correctness, runtime performance, scalability, and Android Studio support that Dagger provides.
Android app requires you to write a substantial amount of boilerplate. Hilt reduces the boilerplate code that is involved in using Dagger in an Android application. Hilt automatically generates and provides the following:
- Components for integrating Android framework classes with Dagger that you would otherwise need to create by hand.
- Scope annotations to use with the components that Hilt generates automatically.
- Predefined bindings to represent Android classes such as Application or Activity.
- Predefined qualifiers to represent
@ApplicationContext
and@ActivityContext
.
Dependency injection with Hilt | Android Developers
To compare Hilt & Dagger read Dependency injection on Android with Hilt.
ServiceLocator
The service locator design pattern also improves decoupling of classes from concrete dependencies. You create a class known as the service locator that creates and stores dependencies and then provides those dependencies on demand.
class ServiceLocator {
private static ServiceLocator instance = null;
private ServiceLocator() {}
public static ServiceLocator getInstance() {
if (instance == null) {
synchronized(ServiceLocator.class) {
instance = new ServiceLocator();
}
}
return instance;
}
public Engine getEngine() {
return new Engine();
}
}
class Car {
private Engine engine = ServiceLocator.getInstance().getEngine();
public void start() {
engine.start();
}
}
class MyApp {
public static void main(String[] args) {
Car car = new Car();
car.start();
}
}
Summary
In my opinion, the DI library choice becomes easy once we decide the Android Library delivery method.
- .aar: if the project requirement is to share .aar with developers, Dagger is good choice as it is compile time and has capabilities to get custom objects from application.
- Source Code: if we are going to share code with developers and Android library is injected into application as source project then Service Locator pattern is good choice for Android Library development as we do not want to inject dependencies to library that can cause conflicts with application’s dependencies. Another drawback is maintaince required to test/update library when new version of Hilt or Dagger is released.