How to get started with Dagger 2 on Android
Posted on July 12, 2018 • 4 minutes • 658 words
Table of contents
This is a small example on how to get started with Dagger 2. I will explain how to create a component that will provide an instance of an Retrofit Api. Please check out my example Github project
If you have absolutely no idea what Dependency Injection and Dagger is, take a look at:
1) Add Dependencies
//Dagger Dependencies
implementation "com.google.dagger:dagger-android:2.15"
implementation "com.google.dagger:dagger-android-support:2.15"
// if you use the support libraries
kapt "com.google.dagger:dagger-android-processor:2.15"
kapt "com.google.dagger:dagger-compiler:2.15"
These are the dependencies just for Dagger2. If you want to follow this tutorial you also need to add Retrofit and RxJava. Take a look at build.gradle .
2) Create a Retrofit interface
I will use https://jsonplaceholder.typicode.com in this example. If you don't know how to use Retrofit, i already explained it here.interface TestApi {
@GET("posts")
fun getPostList(): Single<Response<List>>
}
data class Post(
val id: Int? = null,
val title: String? = null,
val body: String? = null,
val userId: Int? = null
)
3) Create a Module
Create AppModule
@Module
class AppModule(private val application: Application) {
@Provides
@Singleton
fun provideContext(): Application = application
}
A module is a class which is annotated with @Module. A module contains functions which provide/create the needed instances of your dependencies.
In this example the provideContext() will provide an instance of Application wherever Dagger is used to provide it.
Dagger detects that with help of the @Provides annotation and the return type of the function. @Singleton annotates that the provided object will be used as an Singleton. The name of the function is irrelevant.
Create RemoteModule
Let’s create a second module which will provide the Retrofit Api instance. You could use one big module, but it’s better to organize your dependencies in separate modules.
@Module
class RemoteModule {
@Provides
@Singleton
fun provideTestApi(retrofit: Retrofit) = retrofit.create(TestApi::class.java)
@Provides
@Singleton
fun provideRetrofit(): Retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl("https://jsonplaceholder.typicode.com")
.build()
}
provideTestApi() will provide the needed instance of your Retrofit interface. As you can see the function needs a Retrofit object, Dagger will automatically detect that provideRetrofit() will provide the needed instance and use it.
3) Create a Component
@Component(modules = [(AppModule::class), (RemoteModule::class)])
@Singleton
interface AppComponent {
}
Create a Component to bundle your modules A Component is an interface annotated with @Component and the array of modules that this component should contain.
4) Initialize Dagger Components
class App : Application(){
companion object {
lateinit var instance: App
lateinit var appComponent: AppComponent
}
fun initializeDagger() {
appComponent = DaggerAppComponent.builder()
.appModule(AppModule(this))
.remoteModule(RemoteModule())
.build()
}
override fun onCreate() {
super.onCreate()
initializeDagger()
instance = this
}
}
Now you need to initialize your Dagger Components. Note: Don’t wonder that the DaggerAppComponent is missing, it will be automatically generated when you run “Build Project”. Dagger uses this pattern Dagger+“Name of your component class”. So if you would rename AppComponent to MyAppComponent it will generate a DaggerMyAppComponent.java class. Dagger will also generate corresponding functions to the builder for every module that is annotated in your component. In this functions you need to pass a object of your module.
5) Use Dagger
class MainActivity : AppCompatActivity() {
@Inject
lateinit var testApi: TestApi
private fun initializeDagger() = App.appComponent.inject(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initializeDagger()
testApi.getPostList()
....
}
}
Let’s say you want to use the TestApi in your MainActivity To tell Dagger to provide dependencies you first need to inject your appComponent. You do this by adding a function that takes a MainActivity as a parameter to your component .
@Component(modules = [(AppModule::class), (RemoteModule::class)])
@Singleton
interface AppComponent {
fun inject(mainActivity: MainActivity)
}
Now you can use this function in your MainActivity
private fun initializeDagger() = App.appComponent.inject(this)
Make sure to initialize Dagger before you use injected dependencies
Every dependency inside this class that is annotated with @Inject will be provided by your Dagger modules.
…
I hope this blog post helped you to setup a basic project
If you want to do more advanced stuff with Dagger, check out the documentation
Other useful resources: