Перейти к содержанию

Koin

Koin - фреймворк внедрения зависимостей, разработанный для Kotlin. Его классический API описывает модули и создание объектов через Kotlin DSL, без обязательных аннотаций и сгенерированных компонентов. Koin поддерживает Android, Kotlin Multiplatform и другие Kotlin-платформы.

Koin легко добавить в проект, но это всё равно контейнер, для которого нужно осознанно определить владельца, время жизни объектов и конфигурацию запуска.

Основы Koin

Модуль объединяет определения зависимостей. Если граф остаётся читаемым, лучше использовать ссылки на конструкторы:

val appModule = module {
    singleOf(::DefaultUserRepository) bind UserRepository::class
    factoryOf(::LoadUserUseCase)
    viewModelOf(::UserViewModel)
}

Основные типы определений:

Определение Поведение Типичное применение
single Один экземпляр на контейнер Koin База данных, API client, repository
factory Новый экземпляр при каждом разрешении Лёгкие независимые объекты
scoped Один экземпляр внутри явного scope Объекты с временем жизни сессии или экрана
viewModel Создание через Android ViewModelProvider Android ViewModels

single не означает глобальный singleton в JVM. Экземпляр принадлежит Koin application, содержащему определение, и по умолчанию создаётся лениво.

Koin запускают один раз, обычно из Application:

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidContext(this@App)
            modules(appModule)
        }
    }
}

Обычные классы лучше не связывать с Koin и передавать им зависимости через конструктор. Разрешайте зависимости в composition roots, например в точках входа Android, а не вызывайте get() по всему бизнес-коду. Так зависимости остаются явными, а unit-тесты - простыми.

Qualifiers

Qualifier нужен, когда в графе есть несколько определений одного типа:

val networkModule = module {
    single(named("authenticated")) { authenticatedClient(get()) }
    single(named("public")) { publicClient() }
}

Строковые qualifiers лаконичны, но в них легко допустить опечатку. В большом графе их стоит централизовать или заменить типизированными qualifiers. Значения, известные только в месте вызова, можно передать через parametersOf(...); этот механизм стоит оставлять для настоящих runtime-данных, а не скрывать в нём долгоживущую конфигурацию.

Проверка и тестирование

В классическом DSL отсутствующие definitions, неверные qualifiers и некоторые циклы могут обнаружиться только при разрешении конкретной зависимости. Проверяйте модули в тестах и создавайте важные точки входа, а не ограничивайтесь успешным запуском приложения.

Современный Koin также предлагает annotations и DSL на основе compiler plugin, которые могут генерировать wiring и находить больше ошибок во время сборки. Они повышают безопасность, но являются отдельными возможностями и не меняют поведение классического runtime DSL, если проект их не подключил.

В тестах можно использовать тестовые модули, однако для unit-тестов часто проще напрямую вызвать конструктор. Между тестами Koin application нужно изолировать, чтобы избежать общего состояния и зависимости от порядка запуска.

Koin и Hilt

Тема Hilt Классический DSL Koin
Построение графа Сгенерированные компоненты Dagger Runtime-контейнер
Обнаружение ошибок Строгая compile-time проверка В основном при разрешении; помогают проверки модулей
Конфигурация Аннотации, модули и готовые компоненты Definitions через Kotlin DSL
Время жизни Android-объектов Стандартная иерархия сгенерированных компонентов Интеграция с ViewModel и явные scopes
Multiplatform Граф Dagger/Hilt ориентирован на Android/JVM Koin Core поддерживает Kotlin Multiplatform

Hilt - сильный вариант по умолчанию, если большому Android-графу нужны строгая compile-time проверка и стандартные lifecycle components. Koin привлекателен, когда команде важны лаконичная Kotlin-конфигурация, быстрое внедрение или общая Kotlin Multiplatform инфраструктура.

Не стоит выбирать фреймворк только по размеру проекта. Учитывайте опыт команды, build tooling, момент обнаружения ошибок, владение lifecycle, стратегию тестирования и границы платформ в графе зависимостей.

Связанные темы