Ответ
@Provides используется, когда нужно создать объект вручную, а @Binds — когда просто связываешь интерфейс с его реализацией.
Пример замены @Provides на @Binds:
// Было (Provides)
@Module
class AppModule {
@Provides
fun provideRepository(impl: RepositoryImpl): Repository = impl
}
// Стало (Binds) - короче и эффективнее
@Module
interface AppModule {
@Binds
fun bindRepository(impl: RepositoryImpl): Repository
}
Почему @Binds лучше:
- Не создаёт лишних объектов (просто возвращает готовый
impl). - Работает быстрее, т.к. не требует фабричного метода.
- Подходит, если зависимость уже есть в графе (например, через
@Injectконструктор).
Ограничение: @Binds можно использовать только в abstract классе или interface модуля.
Ответ 18+ 🔞
А, ну вот, смотри, классика жанра! Ты когда-нибудь задумывался, зачем в Dagger два способа сделать, по сути, одно и то же? Это как спрашивать, нахуй тебе два вида отвёрток, если можно одной и глаз выковырять. Но нет, ребята, тут есть своя магия.
Так вот, @Provides — это когда ты, блядь, сам всё делаешь. Взял детали, собрал, скрутил, припаял, и вот тебе готовый объект из рук вон плохо, но работает. Ты — фабрика, ты — создатель. А @Binds — это когда ты просто берёшь уже готовую хуйню, которая валяется где-то в углу, и говоришь системе: «Слышь, сука, когда кто-то просит Repository, ты ему вот эту RepositoryImpl подсовывай, понял?». И всё. Никакой возни.
Смотри, как это было и стало:
// Было (Provides) — овердохуища кода для простой хуеты
@Module
class AppModule {
@Provides
fun provideRepository(impl: RepositoryImpl): Repository = impl // Смотри, я создаю! Я молодец!
}
// Стало (Binds) — коротко, ясно, и доверия к коду сразу больше, ёпта
@Module
interface AppModule { // Да-да, интерфейс или абстрактный класс, иначе нихуя не выйдет
@Binds
fun bindRepository(impl: RepositoryImpl): Repository // Просто связываю, без лишних телодвижений
}
А теперь, почему @Binds — это пиздец как хорошо:
- Объектов не плодит. Серьёзно, зачем создавать новый экземпляр, если можно просто ткнуть пальцем в уже существующий? Это как иметь одну зажигалку на всех, а не каждому по новой покупать. Экономия, блядь!
- Быстрее. Потому что не надо вызывать твой фабричный метод, который ещё и проверить надо. Просто связка, и хуй с горы.
- Идеально, когда зависимость уже есть. Например, если у
RepositoryImplконструктор помечен@Inject, и Dagger уже знает, как его собрать. Зачем изобретать велосипед? Берёшь и связываешь.
Но есть, сука, подвох! @Binds можно юзать только в abstract классе или в interface. В обычном классе эта мартышлюшка не взлетит. Так что если тебе вдруг нужно в модуле ещё какую-то хитрожопую логику выполнить (типа настроить объект перед выдачей), то придётся возвращаться к старому доброму @Provides и там уже ебашить.
Короче, правило простое: если можешь использовать @Binds — используй. Это чище, быстрее и правильнее. А @Provides оставь для тех случаев, когда реально нужно руками впендюрить какую-то нестандартную хуйню. Всё, вопрос закрыт, иди работай.