← Назад к вопросам

Как создать свой компонент в 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()
    }
}

Ключевые моменты для запоминания

  1. Обязательные аннотации:

    • @Component — определяет компонент DI
    • @Scope — аннотация для кастомных областей видимости
    • @InstallIn — указывает, в какой компонент устанавливается модуль
  2. Жизненный цикл компонента:

    • Вы сами управляете созданием и уничтожением
    • Компонент живет пока есть на него ссылки
    • Обязательно очищайте компоненты для избежания утечек памяти
  3. Зависимости между компонентами:

    • Используйте dependencies для доступа к зависимостям родительского компонента
    • Через @BindsInstance передавайте контекст или другие параметры
  4. Генерация кода:

    • Hilt сгенерирует Dagger-компоненты с префиксом Dagger (например, DaggerUserSessionComponent)
    • Компиляция должна быть успешной перед использованием

Распространенные проблемы и решения

  • Циклические зависимости: Разделяйте интерфейсы и реализации по разным модулям
  • Утечки памяти: Всегда очищайте ссылки на компоненты в onDestroy()
  • Тестирование: Создавайте тестовые компоненты с mock-зависимостями
  • Мультимодульность: Используйте @InstallIn для указания целевого компонента

Создание кастомных компонентов в Hilt требует глубокого понимания Dagger, но предоставляет гибкость для сложных архитектурных решений, сохраняя при этом преимущества компиляторной проверки зависимостей.

Как создать свой компонент в Hilt? | PrepBro