Dependency injection
Dependency Injection (DI) — это набор паттернов и принципов разработки програмного
обеспечения, которые позволяют писать слабосвязный код. Внедрение зависимостей — это
стиль настройки объекта, при котором поля объекта задаются внешней сущностью. Это
позволяет избежать сильных связей между объектами в коде, которые затрудняют
масштабирование, тестирование и поддержку проекта. Больше теории о внедрении
зависимостей можно почитать здесь.
1 ext.daggerVersion = '2.11'
2
3 dependencies {
4 …
5 //dagger
6 implementation "com.google.dagger:dagger:$daggerVersion"
7 kapt "com.google.dagger:dagger-compiler:$daggerVersion"
8 }
9
Не забудьте также в верхней части файла сборки build.gradle (app) добавить такую строку:
1 package info.fandroid.top100currencies.di
2
3 import android.app.Application
4
5 class App : Application() {
6
7 override fun onCreate() {
8 super.onCreate()
9 }
10 }
11
Чтобы определить этот класс как класс приложения, нужно в файле манифеста прописать
имя класса App в параметре имени секции application:
1 <application
2 android:name=".di.App"
3 …
4
1 package info.fandroid.topcrypts.di
2
3 import android.content.Context
4 import dagger.Module
5 import dagger.Provides
6 import javax.inject.Singleton
7
8 @Module
9 class AppModule(private val app: App) {
10
11 @Provides
12 @Singleton
13 fun provideContext(): Context = app
14
15 }
16
Класс помечен аннотацией @Module, сообщающей Даггеру, что функции этого класса
предоставляют зависимости. Функция provideContext() помечена аннотацией @Provides как
раз для этой цели.
1 package info.fandroid.top100currencies.di
2
3 import dagger.Module
4
5 @Module
6 class ChartModule {
7 }
8
1 package info.fandroid.top100currencies.di
2
3 import dagger.Module
4
5 @Module
6 class MvpModule {
7 }
8
Модуль RestModule содержит функции для предоставления зависимостей Gson,
OkHttpClient, Retrofit и CoinGeckoApi:
1 package info.fandroid.top100currencies.di
2
3 import com.google.gson.Gson
4 import com.google.gson.GsonBuilder
5 import dagger.Module
6 import dagger.Provides
7 import info.fandroid.topcrypts.rest.CoinGeckoApi
8 import okhttp3.OkHttpClient
9 import okhttp3.logging.HttpLoggingInterceptor
10 import retrofit2.Retrofit
11 import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
12 import retrofit2.converter.gson.GsonConverterFactory
13 import java.util.concurrent.TimeUnit
14 import javax.inject.Named
15 import javax.inject.Singleton
16
17 @Module
18 class RestModule {
19
20 @Provides
21 @Singleton
22 fun provideGson(): Gson =
23 GsonBuilder()
24 .setLenient()
25 .create()
26
27 @Provides
28 @Singleton
29 fun provideOkHttpClient(): OkHttpClient =
30 OkHttpClient.Builder()
31
32 .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
33 .connectTimeout(60, TimeUnit.SECONDS)
34 .build()
35
36
37 @Provides
38 @Singleton
39 @Named("COINGECKO_API")
40 fun provideGeckoRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit =
41 Retrofit.Builder()
42 .baseUrl("https://api.coingecko.com/api/v3/")
43 .addConverterFactory(GsonConverterFactory.create(gson))
44 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
45 .client(okHttpClient)
46 .build()
47
48
49 @Provides
50 @Singleton
51 fun provideGeckoApiService(@Named("COINGECKO_API") retrofit: Retrofit): CoinGeckoApi =
52 retrofit.create(CoinGeckoApi::class.java)
53 }
1 package info.fandroid.top100currencies.di
2
3 import dagger.Component
4 import info.fandroid.top100currencies.activities.MainActivity
5 import javax.inject.Singleton
6
7 @Component(modules = arrayOf(AppModule::class, RestModule::class, MvpModule::class,
8 ChartModule::class))
9 @Singleton
10 interface AppComponent {
11
12 fun inject(mainActivity: MainActivity)
13
14
15 }
Данной аннотацией мы говорим Даггеру, что AppComponent содержит четыре модуля:
AppModule, ChartModule, MvpModule и RestModule. Зависимости, которые провайдит
каждый из этих модулей, доступны для всех остальных модулей, объединенных в
компоненте AppComponent.
Пока здесь только одна функция inject(mainActivity: MainActivity), которая сообщает Даггеру
класс, в который мы хотим внедрять зависимости. В дальнейшем мы добавим здесь и
другие классы.
1 package info.fandroid.top100currencies.di
2
3 import android.app.Application
4
5 class App : Application() {
6
7 companion object {
8 lateinit var appComponent: AppComponent
9 }
10
11 override fun onCreate() {
12 super.onCreate()
13 initializeDagger()
14 }
15
16 private fun initializeDagger() {
17 appComponent = DaggerAppComponent.builder()
18 .appModule(AppModule(this))
19 .restModule(RestModule())
20 .mvpModule(MvpModule())
21 .chartModule(ChartModule())
22 .build()
23 }
24 }
25