Ответ
@Provides используется в Dagger для указания способа создания объекта, когда:
- Объект нельзя создать через
@Inject(например, интерфейсы или сторонние библиотеки). - Требуется кастомизация создания (например, конфигурация Retrofit или OkHttpClient).
- Зависимость требует runtime-аргументов (через
@BindsInstanceили параметры в модуле).
Пример:
@Module
class NetworkModule {
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.build()
}
}
⚠️ Если можно использовать @Inject или @Binds (для интерфейсов), лучше выбрать их — код будет чище.
Ответ 18+ 🔞
А, ну это же классика, ёпта! Смотри, сейчас разжуём, что за зверь такой — @Provides.
Представь, что Dagger — это такой дотошный прораб на стройке твоего приложения. Он готов сам замешивать бетон и класть кирпичи, но только если ты дашь ему чёткую схему, как это делать. @Inject на конструкторе — это как сказать: «Вот, прораб, беги на склад, там все детали для «Мустанга» лежат, собери мне его». А @Provides — это когда деталь настолько хитрая или нестандартная, что тебе приходится самому лезть в ящик с инструментами и буквально руками показывать, как её скрутить.
Когда этот твой @Provides реально нужен?
-
Когда объект — это интерфейс или абстрактный класс. Ну ясно же, ёбать копать, его нельзя просто «newнуть»! Dagger смотрит на
SomeInterfaceи такой: «Чувак, а какую конкретную реализацию тебе запихнуть? Я не телепат, блядь». Вот тут ты и пишешь метод, который говорит: «НаSomeInterface— вот этот вотSomeImplementationи возвращай». -
Когда объект из чужой библиотеки. Retrofit, OkHttpClient, Gson — ты же не можешь в их исходники залезть и
@Injectв конструктор впендюрить? Придётся самому, вручную, в модуле объяснять Dagger'у, как эту штуку собрать. Это прям его родная стихия. -
Когда создание — это целый ритуал. Допустим, тебе нужен не просто
OkHttpClient, а такой, который с таймаутами, логгером и интерцепторами. Вот тут ты разворачиваешься и в методе с@Providesпишешь целую поэму изBuilder().
Смотри, как это выглядит на практике, чтобы совсем ни хуя себе не осталось:
@Module
class NetworkModule {
@Provides
fun provideOkHttpClient(): OkHttpClient {
// Вот тут ты — бог и царь. Настраивай как хочешь.
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // Чтоб не тупил
.addInterceptor(LoggingInterceptor()) // Чтоб всё логировал
.build()
}
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
// А сюда Dagger сам подсунет тот OkHttpClient, что мы создали выше. Красота!
return Retrofit.Builder()
.baseUrl("https://api.mojservis.ru/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
НО! Важное предупреждение, чтоб потом не было волнения ебать.
Если можно обойтись без этого — обходись. Если класс твой, и в его конструктор можно воткнуть @Inject — делай так. Если привязываешь интерфейс к реализации — сначала посмотри на @Binds, он часто лаконичнее. @Provides — это как мощная дрель: для гипсокартона она овердохуища, но чтобы повесить картину, хватит и молотка с гвоздём. Не усложняй без нужды, а то получится пиздопроебибна с модулями на ровном месте.