В чем отличие Hilt от Koin и почему Hilt более гибкий?
Что проверяют
Понимаете ли вы разницу между проверкой графа зависимостей при сборке и во время работы, и готовы ли спорить с предпосылкой вопроса. «Hilt более гибкий» верно не во всём, и интервьюеру интересно, заметите ли вы это.
Как отвечать
Начните с механики:
- Hilt: надстройка над Dagger. Граф строится при сборке через kapt или KSP, генерируется обычный код без рефлексии. Нет привязки или есть конфликт, и сборка упадёт;
- Koin: DI на Kotlin DSL (
module { single { } factory { } viewModel { } }), по умолчанию без кодогенерации. Зависимости разрешаются при запросе, отсутствие привязки обнаружится падением в рантайме, если не проверять конфигурацию в тесте черезverify().
За что Hilt называют гибким:
- компоненты под жизненный цикл Android:
SingletonComponent,ActivityRetainedComponent,ViewModelComponent,ActivityComponent,FragmentComponentи скоупы вроде@Singletonи@ViewModelScoped; - возможности Dagger: мультибиндинги
@IntoSetи@IntoMap,@AssistedInjectдля параметров из рантайма, квалификаторы,@EntryPointдля классов, куда нельзя внедрить напрямую; - тесты:
@TestInstallInи@UninstallModulesподменяют модули целиком.
Где гибче Koin: модули подгружаются и выгружаются на лету через loadKoinModules, он работает в Kotlin Multiplatform, у него ниже порог входа и нет добавки к времени сборки. Hilt привязан к Android и заметно утяжеляет сборку, особенно на kapt.
Итог: Hilt даёт строгость и раннее обнаружение ошибок на больших проектах, Koin даёт простоту и динамику. Выбор зависит от размера команды, планов на KMP и требований к скорости сборки.
Где спотыкаются
Соглашаются с «Hilt гибче» без оговорок. Точнее сказать: строже и безопаснее, а по динамике он как раз уступает.
Говорят, что Koin работает на рефлексии. Он опирается на лямбды и reified-дженерики Kotlin, его главная цена это ошибки в рантайме, а не скорость.
Утверждают, что в Koin нет скоупов или что он создаёт всё при каждом запросе. single создаётся один раз и лениво, factory каждый раз заново, есть и scope.