Что такое AssistedInject в Dagger?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое AssistedInject в Dagger
AssistedInject — это дополнение к библиотеке Dagger, которое позволяет внедрять зависимости, часть которых предоставляется Dagger (через механизм внедрения), а часть — передаётся явно (вручную) в момент создания объекта. Это особенно полезно, когда некоторые параметры конструктора известны только во время выполнения, а не на этапе компиляции.
Проблема, которую решает AssistedInject
В классическом Dagger все зависимости для объекта должны быть предоставлены графом зависимостей на этапе компиляции. Однако часто возникают ситуации, когда объект требует параметры, которые:
- Динамичны (например, идентификатор пользователя из Intent в Android).
- Зависят от контекста выполнения.
- Не могут быть известны во время компиляции и должны передаваться извне.
Раньше для этого приходилось создавать фабрики вручную или использовать другие обходные пути. AssistedInject решает эту проблему элегантно и с минимальным шаблонным кодом.
Как работает AssistedInject
- Аннотация
@AssistedInjectпомечается на конструктор класса, который нуждается в "помощных" параметрах. - Аннотация
@Assistedиспользуется для параметров конструктора, которые должны передаваться явно. - Генерируемая фабрика: Dagger автоматически создаёт фабрику (
Factory) для такого класса, которая принимает "помощные" параметры, а остальные зависимости получает из графа.
Пример использования AssistedInject
Рассмотрим типичный случай в Android — создание ViewModel, которой нужно передать идентификатор элемента.
Без AssistedInject пришлось бы создавать фабрику вручную:
class ProductViewModel(
private val productId: String,
private val repository: ProductRepository
) : ViewModel() { ... }
class ProductViewModelFactory(
private val repository: ProductRepository,
private val productId: String
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ProductViewModel(productId, repository) as T
}
}
С AssistedInject код становится значительно проще:
// 1. Добавляем зависимость в build.gradle
// implementation 'com.google.dagger:dagger-assist:2.46' (включено в Dagger с версии 2.33)
// 2. Помечаем конструктор
class ProductViewModel @AssistedInject constructor(
@Assisted private val productId: String, // Параметр, передаваемый явно
private val repository: ProductRepository // Зависимость из графа Dagger
) : ViewModel() {
// 3. Объявляем фабрику (интерфейс с аннотацией @AssistedFactory)
@AssistedFactory
interface Factory {
fun create(productId: String): ProductViewModel
}
... // Логика ViewModel
}
3. Внедрение фабрики в Activity/Fragment:
class ProductActivity : AppCompatActivity() {
@Inject
lateinit var viewModelFactory: ProductViewModel.Factory
override fun onCreate(savedInstanceState: Bundle?) {
(application as MyApp).appComponent.inject(this)
super.onCreate(savedInstanceState)
val productId = intent.getStringExtra("PRODUCT_ID")!!
val viewModel = viewModelFactory.create(productId)
// Используем viewModel
}
}
Ключевые преимущества AssistedInject
- Уменьшение шаблонного кода: Не нужно писать фабрики вручную.
- Безопасность типов: Генерируемый код является типобезопасным.
- Интеграция с Dagger: Полная совместимость с остальным графом зависимостей.
- Поддержка Hilt:
AssistedInjectполностью работает с Hilt — официальной библиотекой для внедрения зависимостей в Android. - Гибкость: Можно комбинировать "помощные" параметры и зависимости из графа в любом порядке.
Ограничения и нюансы
- Только для конструкторов:
@Assistedможно применять только к параметрам конструктора. - Все или ничего: Если используется
@AssistedInject, все "помощные" параметры должны быть помечены@Assisted. - Уникальные имена: В одном конструкторе все
@Assistedпараметры должны иметь уникальные имена или быть связаны через@Assisted("имя"). - Не для всех объектов: Лучше всего подходит для объектов, создаваемых во время выполнения с динамическими параметрами (ViewModel, Presenter, UseCase и т.д.).
Альтернативы AssistedInject
- Ручное создание фабрик (больше кода, но полный контроль).
- Использование
SavedStateHandleв Hilt для ViewModel (специальный случай для сохранения состояния). - Кастомные решения на
ProviderилиLazy.
Заключение
AssistedInject — мощное и элегантное решение для сценариев, когда объект требует смешанных зависимостей: часть из графа Dagger, часть — динамические параметры времени выполнения. Он значительно снижает количество шаблонного кода, улучшает читаемость и поддерживаемость, особенно в связке с Hilt для Android-разработки. Начиная с Dagger 2.33, эта функциональность включена в основную библиотеку, что подтверждает её важность и востребованность в реальных проектах.