Ошибка Dagger: "Prefer to run the dagger processor over that class instead" в Kotlin
Причина ошибки
Ошибка Prefer to run the dagger processor over that class instead в Kotlin-проектах с Dagger обычно связана с тем, что Dagger не может корректно обработать аннотации из-за особенностей работы kapt (Kotlin Annotation Processing Tool). В 90% случаев это происходит, когда вы используете нестатические методы в @Module или когда модуль объявлен как data class или object без правильных модификаторов.
В вашем примере модуль объявлен как обычный класс (не object и не abstract). Для Dagger это означает, что ему нужно создавать экземпляр модуля, что в Kotlin может вызвать конфликты с kapt. Dagger "видит" класс, но не может сгенерировать для него корректный код, так как Kotlin компилятор может изменить сигнатуру или добавить скрытые методы (например, component1() для data class, но у вас не data class — это хорошо).
Однако самая частая причина — отсутствие аннотации @JvmStatic на методах @Provides внутри модуля-объекта. Давайте посмотрим на исправленный код:
@Module
object NetworkModule { // Используем object вместо class
@Provides
@Singleton
@JvmStatic // Обязательно для методов в object-модулях
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
Почему это работает?
- object — это синглтон в Kotlin, и Dagger не нужно создавать его экземпляр, что снижает нагрузку на kapt.
- @JvmStatic — говорит Kotlin сгенерировать статический метод для Java-совместимости. Dagger (написанный на Java) ожидает увидеть статические методы в модулях, объявленных как object или abstract.
- Если ваш модуль должен иметь состояние, используйте abstract class вместо class.
Альтернативное решение (если не хотите object)
Можно оставить класс, но добавить конструктор без параметров и аннотацию @Module(includes = [...]):
@Module
class NetworkModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
// В компоненте:
@Component(modules = [NetworkModule::class])
@Singleton
interface AppComponent { ... }
Но этот вариант менее надёжен — Dagger может снова выдать ошибку, если в проекте есть другие Kotlin-конструкции (например, inline-функции или свойства с backing field).
Дополнительные советы
- Убедитесь, что у вас подключён kapt в build.gradle:
id 'kotlin-kapt'. - Проверьте версии Dagger и Kotlin — они должны быть совместимы. Например, Dagger 2.48+ требует Kotlin 1.8+.
- Если ошибка остаётся, попробуйте добавить
@Module(includes = [...])или использовать@Bindsвместо@Providesдля интерфейсов.
Проблема с kapt и многомодульностью
Если вы используете многомодульный проект (например, feature-модули), ошибка Prefer to run the dagger processor over that class instead может возникать из-за того, что Dagger не может найти сгенерированный код в соседнем модуле. Решение — убедиться, что kapt настроен во всех модулях, где есть Dagger-аннотации, и что зависимость между модулями корректна.
// В build.gradle каждого модуля с Dagger:
plugins {
id 'kotlin-kapt'
}
dependencies {
implementation 'com.google.dagger:dagger:2.48'
kapt 'com.google.dagger:dagger-compiler:2.48'
}
Также проверьте, не используете ли вы @Inject на конструкторе data class — это частая причина путаницы для Dagger. Если у вас есть data class с @Inject constructor, замените его на обычный класс или добавьте @JvmOverloads.
Ещё один трюк: иногда помогает очистка кеша kapt: ./gradlew clean и удаление папки .gradle в корне проекта.