Что такое Assisted Factory в Dagger?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Assisted Factory в Dagger?
Assisted Factory — это паттерн и встроенная функция в Dagger 2, которая позволяет внедрять зависимости, часть которых предоставляется через DI-контейнер, а часть — динамически во время выполнения (например, параметры, известные только в рантайме). Это расширение классического паттерна "Assisted Injection", упрощающее его использование за счёт автоматической генерации фабричных классов.
Проблема, которую решает Assisted Factory
В классическом Dagger все зависимости "резолвятся" на этапе компиляции. Однако на практике часто возникают объекты, для создания которых нужны:
- Статические зависимости (из графа Dagger): например,
Repository,Context,ApiService. - Динамические параметры (runtime-значения): например,
userId,requestId,flags.
Прямое использование @Inject конструктора здесь невозможно, так как Dagger не может предоставить runtime-параметры. Assisted Factory решает эту проблему, разделяя ответственность: Dagger предоставляет то, что знает, а программист — то, что известно только в рантайме.
Как это работает
- Помечаем конструктор целевого класса аннотацией
@AssistedInject. - Помечаем runtime-параметры аннотацией
@Assisted. - Объявляем интерфейс фабрики с методом, принимающим assisted-параметры и возвращающим целевой класс. Помечаем его
@AssistedFactory. - Dagger автоматически генерирует реализацию этой фабрики, внедряя в неё статические зависимости.
Практический пример
Предположим, у нас есть UserViewModel, которому нужен UserRepository из графа и динамический userId.
// 1. Целевой класс с @AssistedInject
class UserViewModel @AssistedInject constructor(
private val userRepository: UserRepository, // Статическая зависимость
@Assisted private val userId: String // Динамический параметр
) {
fun getUser() = userRepository.getUser(userId)
}
// 2. Фабрика с @AssistedFactory
@AssistedFactory
interface UserViewModelFactory {
fun create(userId: String): UserViewModel
}
// 3. Внедрение и использование фабрики
class UserActivity @Inject constructor(
private val viewModelFactory: UserViewModelFactory
) {
fun onCreate() {
val userId = intent.getStringExtra("USER_ID") // Runtime-значение
val viewModel = viewModelFactory.create(userId)
// Работаем с viewModel...
}
}
Dagger сгенерирует реализацию UserViewModelFactory, которая при вызове create(userId):
- Возьмёт
UserRepositoryиз своего графа. - Передаст его вместе с
userIdв конструкторUserViewModel.
Ключевые преимущества
- Упрощение кода: Не нужно писать фабрики вручную или использовать
@BindsInstanceв сложных сценариях. - Типобезопасность: Генерация происходит на этапе компиляции, ошибки обнаруживаются рано.
- Чистое разделение ответственности: DI-контейнер управляет статическими зависимостями, клиентский код — динамическими.
- Интеграция с ViewModel: Особенно полезно в Android с архитектурными компонентами, где
ViewModelне может иметь параметров в конструкторе при использовании стандартныхViewModelProvider.Factory.
Отличие от классического Assisted Injection
В более ранних версиях Dagger использовался отдельный паттерн с @AssistedModule и @AssistedInject, где фабрику нужно было привязывать вручную. Assisted Factory (появился в Dagger 2.31+) — это эволюция этого подхода, где достаточно только @AssistedFactory интерфейса, а Dagger делает всю остальную работу автоматически.
Важные нюансы
- Каждый
@Assistedпараметр должен иметь уникальный ключ (можно задать через@Assisted("key")), если типы повторяются. - Фабрика должна быть интерфейсом с одним методом, возвращающим тип с
@AssistedInject. - Статические и динамические зависимости нельзя смешивать — все
@Assistedпараметры должны быть переданы в фабричный метод. - Assisted Factory идеально сочетается с
ViewModel, когда нуженSavedStateHandle(как runtime-параметр) и другие зависимости из графа.
Заключение
Assisted Factory — это мощный и элегантный механизм Dagger для управления гибридными зависимостями, сочетающий преимущества compile-time безопасности и runtime-гибкости. Он значительно снижает шаблонный код, устраняя необходимость в ручном написании фабрик, и является предпочтительным способом реализации "assisted injection" в современных проектах на Dagger. Его использование делает код более чистым, тестируемым и соответствующим принципам чистой архитектуры, где зависимости явно разделены на статические и динамические.