Что такое инверсия контроля
Что проверяют
Понимаете ли вы принцип шире, чем «подключить Hilt». В Android инверсия контроля встречается на каждом шаге, и интервьюер ждёт, что вы это заметите. Следом обычно спрашивают, чем Hilt отличается от Koin и почему Service Locator считают компромиссом.
Как отвечать
Инверсия контроля означает, что поток выполнения и создание зависимостей определяет не ваш код, а внешний механизм. У неё два проявления:
- управление потоком: фреймворк сам вызывает ваш код. Система создаёт
Activityи вызываетonCreate,onResume,onDestroy;RecyclerViewдёргаетonBindViewHolder; - управление зависимостями: класс получает зависимости снаружи, а не создаёт их. Реализуется через внедрение зависимостей или Service Locator.
Инструменты в Android:
- Hilt: надстройка над Dagger, граф проверяется при сборке, и ошибка конфигурации ломает компиляцию, а не приложение у пользователя.
@HiltAndroidAppнаApplication,@AndroidEntryPointна экранах,@HiltViewModelс@Inject constructor, модули с@InstallIn(SingletonComponent::class). Кодогенерацию сейчас переводят с kapt на KSP; - Koin: DSL на Kotlin без кодогенерации, зависимости разрешаются в рантайме. Пропущенная зависимость всплывёт при запуске, поэтому граф проверяют тестом
verify(); - ручной DI: контейнер в
Application, как в официальном гайде Android.
Отдельно стоит объяснить, почему Activity и Fragment получают зависимости через поля, а ViewModel через конструктор: система пересоздаёт экраны сама и вызывает конструктор без аргументов.
Где спотыкаются
Называют IoC и DI синонимами и не вспоминают про колбэки жизненного цикла, хотя это самый наглядный пример инверсии в Android.
Передают данные во Fragment через собственный конструктор. После пересоздания системой фрагмент восстанавливается конструктором без аргументов: данные теряются или падает Fragment.InstantiationException. Данные идут через arguments, зависимости через DI или FragmentFactory.
Внедряют Context конкретной Activity в синглтон. Объект живёт дольше экрана, и Activity утекает вместе со всем деревом view. Для долгоживущих зависимостей нужен @ApplicationContext.