← Назад к вопросам
Как создать свой компонент в Hilt?
2.0 Middle🔥 111 комментариев
#Dependency Injection#Архитектура и паттерны
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Создание собственных компонентов в Hilt
Зачем нужны кастомные компоненты?
Стандартная иерархия компонентов Hilt (Application → Activity → Fragment → View) покрывает большинство случаев, но иногда требуется создание специализированных компонентов для:
- Изолированных функциональных модулей
- Пользовательских областей видимости (scopes)
- Legacy-кода, который нельзя переписать под стандартные компоненты
- Тестирования с кастомными зависимостями
Основные подходы к созданию компонентов
1. Наследование от существующих компонентов
Самый распространенный способ — расширение стандартного компонента:
// Объявляем новый scope
@Scope
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class CustomScope
// Создаем компонент, наследующий от ActivityComponent
@CustomScope
@Component(dependencies = [ActivityComponent::class])
interface CustomComponent {
fun inject(service: CustomService)
@Component.Factory
interface Factory {
fun create(
@BindsInstance applicationContext: Context,
activityComponent: ActivityComponent
): CustomComponent
}
}
2. Самостоятельный компонент без родителя
Для полностью изолированной функциональности:
@Component(modules = [CustomModule::class])
@CustomScope
interface StandaloneComponent {
val repository: CustomRepository
val apiService: CustomApiService
@Component.Builder
interface Builder {
@BindsInstance
fun context(context: Context): Builder
fun build(): StandaloneComponent
}
}
Полный пример реализации
Шаг 1: Определяем Scope и модули
// CustomScope.kt
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class UserSessionScope
// CustomModule.kt
@Module
@InstallIn(SingletonComponent::class)
object CustomModule {
@Provides
@Singleton
fun provideCustomDependency(): CustomDependency {
return CustomDependencyImpl()
}
}
// SessionModule.kt
@Module
@InstallIn(UserSessionComponent::class)
object SessionModule {
@Provides
@UserSessionScope
fun provideSessionManager(
api: ApiService,
preferences: SharedPreferences
): SessionManager {
return SessionManagerImpl(api, preferences)
}
}
Шаг 2: Создаем компонент
@UserSessionScope
@Component(
dependencies = [SingletonComponent::class],
modules = [SessionModule::class]
)
interface UserSessionComponent {
fun sessionManager(): SessionManager
fun inject(fragment: ProfileFragment)
@Component.Factory
interface Factory {
fun create(
singletonComponent: SingletonComponent
): UserSessionComponent
}
}
Шаг 3: Интеграция с Hilt
// CustomApplication.kt
@HiltAndroidApp
class CustomApplication : Application() {
private var userSessionComponent: UserSessionComponent? = null
fun createUserSessionComponent(): UserSessionComponent {
return DaggerUserSessionComponent
.factory()
.create(
(this as HasAndroidInjector)
.androidInjector() as SingletonComponent
).also {
userSessionComponent = it
}
}
fun getUserSessionComponent(): UserSessionComponent? {
return userSessionComponent
}
fun clearUserSessionComponent() {
userSessionComponent = null
}
}
Шаг 4: Использование в Activity/Fragment
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var userSessionComponent: UserSessionComponent
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Создаем компонент при старте сессии
if (userLoggedIn()) {
userSessionComponent = (application as CustomApplication)
.createUserSessionComponent()
}
}
private fun useSessionDependency() {
val sessionManager = userSessionComponent.sessionManager()
sessionManager.refreshToken()
}
}
Ключевые моменты для запоминания
-
Обязательные аннотации:
@Component— определяет компонент DI@Scope— аннотация для кастомных областей видимости@InstallIn— указывает, в какой компонент устанавливается модуль
-
Жизненный цикл компонента:
- Вы сами управляете созданием и уничтожением
- Компонент живет пока есть на него ссылки
- Обязательно очищайте компоненты для избежания утечек памяти
-
Зависимости между компонентами:
- Используйте
dependenciesдля доступа к зависимостям родительского компонента - Через
@BindsInstanceпередавайте контекст или другие параметры
- Используйте
-
Генерация кода:
- Hilt сгенерирует Dagger-компоненты с префиксом
Dagger(например,DaggerUserSessionComponent) - Компиляция должна быть успешной перед использованием
- Hilt сгенерирует Dagger-компоненты с префиксом
Распространенные проблемы и решения
- Циклические зависимости: Разделяйте интерфейсы и реализации по разным модулям
- Утечки памяти: Всегда очищайте ссылки на компоненты в
onDestroy() - Тестирование: Создавайте тестовые компоненты с mock-зависимостями
- Мультимодульность: Используйте
@InstallInдля указания целевого компонента
Создание кастомных компонентов в Hilt требует глубокого понимания Dagger, но предоставляет гибкость для сложных архитектурных решений, сохраняя при этом преимущества компиляторной проверки зависимостей.