Android + Dagger2

Guowei Lv

1 minute read

This is a simple one. No more explanation, just paste the code here. @UiThread @Module class AppModule { @Provides @AppScope @Retrofit1 fun retrofit1(urlProvider: UrlProvider): Retrofit { return Retrofit.Builder() .baseUrl(urlProvider.baseUrl1()) .addConverterFactory(GsonConverterFactory.create()) .build() } @Provides @AppScope @Retrofit2 fun retrofit2(): Retrofit { return Retrofit.Builder() .baseUrl(urlProvider().baseUrl2()) .addConverterFactory(GsonConverterFactory.create()) .build() } @Provides @AppScope fun stackOverflowApi(@Retrofit1 retrofit: Retrofit): StackoverflowApi = retrofit.create(StackoverflowApi::class.java) @Provides @AppScope fun urlProvider(): UrlProvider = UrlProvider() } @Qualifier annotation class Retrofit1() @Qualifier annotation class Retrofit2()

Guowei Lv

1 minute read

Let’s create a ScreensNavigator interface: interface ScreensNavigator { fun navigateBack() fun toQuestionDetails(questionId: String) } And ScreensNavigatorImpl implements it: class ScreensNavigatorImpl @Inject constructor(private val activity: AppCompatActivity) : ScreensNavigator { override fun navigateBack() { activity.onBackPressed() } override fun toQuestionDetails(questionId: String) { QuestionDetailsActivity.start(activity, questionId) } } Now we have a problem that in activities and fragments we want to inject the interface type: @Inject lateinit var screensNavigator: ScreensNavigator But Dagger only knows how to create ScreensNavigatorImpl.

Dependency Injection in Android With Dagger2 (7)

Static Provider Methods and Component Builder

Guowei Lv

2 minute read

One fact: it is more performant to make the all provider methods inside Modules static. But for Modules that have bootstrap dependencies, this is impossible. Let’s take ActivityModule as example. @Module class ActivityModule(private val activity: AppCompatActivity) { @Provides fun activity(): AppCompatActivity = activity @Provides fun layoutInflater(activity: AppCompatActivity): LayoutInflater = LayoutInflater.from(activity) @Provides fun fragmentManager(activity: AppCompatActivity) = activity.supportFragmentManager @Provides @ActivityScope fun screensNavigator(activity: AppCompatActivity) = ScreensNavigator(activity) } We can easily make fun layoutInflater(), fragmentManager() and screensNavigator static methods.

Guowei Lv

1 minute read

Components can have multiple Modules. So if you have huge Modules that provide tons of services, it is good to split it up. Let’s create a UseCaseModule to hanle all the UseCases. @Module class UseCasesModule { @Provides fun fetchQuestionsUseCase(stackOverflowApi: StackoverflowApi) = FetchQuestionsUseCase(stackOverflowApi) @Provides fun fetchQuestionDetailsUseCase(stackOverflowApi: StackoverflowApi) = FetchQuestionDetailsUseCase(stackOverflowApi) } Some dagger conventions: 1. Components can use more than 1 module. 2. Modules of the same Component share the same object-graph.

Guowei Lv

2 minute read

In previous post, we introduced the component dependencies. But there is one interesting subtlety: If Component B depends on Component A, B has access to all A’s exposed objects. Note that there is a difference between what a component exposes and what it provides. Let’s look at PresentationComponent and ActivityComponent. @PresentationScope @Component(dependencies =[ActivityComponent::class], modules =[PresentationModule::class]) interface PresentationComponent { fun inject(fragment: QuestionsListFragment) fun inject(questionDetailsActivity: QuestionDetailsActivity) } Here in PresentationComponent, even though it provides all the objects that QuestionsListFragment and QuestionDetailsActivity need, it exposes nothing.