Если вы пишите Android-приложение на Kotlin и хотите использовать инъекцию зависимостей, взгляните на платформу Kodein. Она создана специально для Android и Kotlin. Не буду глубоко погружаться в паттерн dependency injection в этом посте. Если вы с ним не знакомы, рекомендую загуглить Dagger 2 для ознакомления.
Сегодня мы вместе с Вами взглянем на Kodein в действии на примере. Предположим, мы хотим занижектить singleton инстанс retrofit-а в каком-либо месте нашего приложения.
Сначала, добавим Kodein зависимости в gradle файл:
implementation "org.kodein.di:kodein-di-generic-jvm:6.1.0" implementation "org.kodein.di:kodein-di-framework-android-core:6.1.0" implementation "org.kodein.di:kodein-di-framework-android-x:6.1.0"
Имплементим интерфейс KodeinAware в классе приложения Application. Будет необходимо переопределить kodein val и в нем инициализировать инстанс Retrofit-а:
class App : Application(), KodeinAware { override val kodein = Kodein { import(androidXContextTranslators) bind<Retrofit>() with singleton { Retrofit.Builder() .client(OkHttpClient().newBuilder().build()) .baseUrl("htttp://example.com") .addCallAdapterFactory(CoroutineCallAdapterFactory()) .build() } } }
Все зависимости внутри блока Kodein формируются по следующему паттерну:
bind<TYPE>() with
далее идет метод создания и использования объекта: «singleton», «provides» or «factory»
«singleton» говорит сам за себя, «provides» каждый раз генерит новый объект. Если нужен кастомный объект, тогда используйте фабрику: «factory«; как и «provides» он создает каждый раз новый объект, но с конструктором.
Теперь, когда мы объявили зависимости, давайте использовать их!
Заинжектим наш инстанс Retrofit-а в Activity/Fragment или, если вы используете MVP паттерн, то в presenter. Разница в наличии контекста: в презентере его нет по умолчанию. Попробуем сначала внедрить Retrofit в Activity.
И снова заимплементим интерфейс KodeinAware и получим инстанс:
class MainActivity : AppCompatActivity, KodeinAware{ override val kodein: Kodein by kodein() private val retrofit: Retrofit by instance() ... // use retrofit
А теперь, если мы хотим использовать ретрофит в классе без Android контекста,
то нам нужно всего лишь передать туда Context для того, чтобы создать инстанс Kodein. Для этого я использовал applicationContext.
Добавьте следующие строки в класс Application:
... override fun onCreate() { super.onCreate() instance = this } companion object { lateinit var instance: App private set } ...
И теперь в презентере:
class MyPresenterImpl : IMyPresenter, KodeinAware { override val kodein by kodein(App.instance) override val kodeinContext = kcontext(App.instance) private val retrofit: Retrofit by instance() ... // use retrofit
Ссылка на официальную документацию