Какие преимущества дает кодогенерация Dagger на этапе компиляции
Что проверяют
Понимаете ли вы, чем Dagger отличается от DI на рефлексии и что именно происходит при сборке. Следом спрашивают про Hilt, про kapt и KSP, иногда просят сравнить с Koin.
Как отвечать
Dagger это annotation processor: по @Component, @Module, @Provides, @Binds и @Inject он при компиляции строит граф зависимостей и генерирует обычный Java-код, например класс DaggerAppComponent с фабриками. В рантайме нет рефлексии и поиска по карте, только вызовы конструкторов.
Что это даёт:
- ошибки графа при сборке: забытая привязка, цикл, дубль или неверный скоуп дают ошибку компиляции с путём по графу, а не краш у пользователя на редком экране;
- скорость в рантайме: рефлексии нет, а на Android она заметно дорогая, особенно на холодном старте;
- прозрачный код: сгенерированные классы лежат в
build/generated, их можно прочитать и пройти отладчиком; - дружба с R8: объекты создаются явными вызовами, поэтому не нужны keep-правила для классов, которые иначе создавались бы рефлексией;
- статическая проверка скоупов:
@Singletonи свои скоупы проверяются компилятором, компонент с неподходящим скоупом не соберётся.
Hilt построен поверх Dagger: даёт готовые компоненты для Application, Activity, ViewModel и сохраняет те же гарантии времени компиляции.
Цену тоже назовите. Кодогенерация удлиняет сборку, особенно через kapt, который гоняет Kotlin через Java-стабы. Dagger и Hilt поддерживают KSP, и переход на него ускоряет сборку. Ошибки в большом графе бывают длинными и тяжёлыми для чтения.
Где спотыкаются
Ставят Koin в один ряд с Dagger. Koin в классическом DSL-варианте это сервис-локатор: зависимости он находит в рантайме, и ошибка в графе проявится при запуске или в отдельном проверочном тесте.
Утверждают, что Dagger совсем бесплатен. В рантайме накладных расходов почти нет, а платите вы временем сборки.
Не могут объяснить разницу @Binds и @Provides. @Binds объявляется абстрактным методом, только связывает интерфейс с реализацией и генерирует меньше кода.