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

Какая аннотация у фрагмента, чтобы все работало в Dagger?

2.0 Middle🔥 201 комментариев
#Android компоненты#Dependency Injection

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Аннотации Fragment для корректной работы с Dagger

Чтобы Fragment корректно работал с Dagger (особенно с Dagger Hilt), необходимо использовать несколько ключевых аннотаций в зависимости от версии и подхода. Основная современная аннотация — @AndroidEntryPoint, но есть важные нюансы.

Основные аннотации для различных сценариев

1. @AndroidEntryPoint (Dagger Hilt)

Для современного подхода с Hilt (официальная библиотека для внедрения зависимостей от Google) используется именно эта аннотация. Она заменяет все предыдущие подходы и автоматически генерирует необходимые компоненты.

import androidx.fragment.app.Fragment
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MyFragment : Fragment() {
    // Внедрение зависимостей через @Inject
    @Inject
    lateinit var repository: MyRepository
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // repository уже инициализирована
    }
}

Важные условия для @AndroidEntryPoint:

  • Родительская Activity также должна быть аннотирована @AndroidEntryPoint
  • Используется с Dagger Hilt (требует настройки в build.gradle)
  • Автоматически обрабатывает жизненный цикл Fragment

2. Ручной Dagger (без Hilt)

Если вы используете чистый Dagger без Hilt, подход отличается:

import dagger.android.support.DaggerFragment

class MyFragment : DaggerFragment() {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Внедрение происходит автоматически через DaggerFragment
    }
}

Альтернативный подход с кастомной интеграцией:

class MyFragment : Fragment() {
    @Inject
    lateinit var dependency: MyDependency
    
    override fun onAttach(context: Context) {
        // Получаем компонент из Activity
        (activity as MyActivity).component
            .fragmentComponent()
            .create(this)
            .inject(this)
        super.onAttach(context)
    }
}

Конфигурация Gradle для Hilt

Для работы @AndroidEntryPoint необходима настройка:

// build.gradle (project)
plugins {
    id 'com.google.dagger.hilt.android' version '2.48' apply false
}

// build.gradle (app)
plugins {
    id 'kotlin-kapt'
    id 'com.google.dagger.hilt.android'
}

dependencies {
    implementation "com.google.dagger:hilt-android:2.48"
    kapt "com.google.dagger:hilt-compiler:2.48"
    
    // Для поддержки AndroidX
    implementation 'androidx.hilt:hilt-navigation-fragment:1.0.0'
}

Работа с ViewModel в Hilt Fragment

Частая ситуация — внедрение ViewModel в аннотированный Fragment:

@AndroidEntryPoint
class MyFragment : Fragment() {
    // ViewModel с поддержкой Hilt
    private val viewModel: MyViewModel by viewModels()
    
    // Или с кастомной фабрикой
    private val viewModel: MyViewModel by viewModels { 
        viewModelFactory 
    }
}

Для ViewModel, которая требует свои зависимости:

@HiltViewModel
class MyViewModel @Inject constructor(
    private val repository: MyRepository
) : ViewModel()

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

  1. Основная аннотация: @AndroidEntryPoint для Hilt
  2. Обязательное условие: Activity, содержащая Fragment, должна быть также аннотирована @AndroidEntryPoint
  3. Инициализация полей: Поля с @Inject инициализируются после super.onCreate() в Activity и после super.onAttach() в Fragment
  4. Избегайте раннего доступа: Не обращайтесь к внедренным полям в конструкторе или init-блоках
  5. Навигация: При использовании Navigation Component все Fragment в графе навигации должны использовать @AndroidEntryPoint

Типичные ошибки и решения

// ❌ НЕПРАВИЛЬНО - ранний доступ к зависимости
@AndroidEntryPoint
class MyFragment : Fragment() {
    @Inject
    lateinit var repository: MyRepository
    
    init {
        // repository еще не инициализирована!
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Здесь уже можно использовать repository
    }
}
// ✅ ПРАВИЛЬНО - использование в соответствующих методах жизненного цикла
@AndroidEntryPoint
class MyFragment : Fragment() {
    @Inject
    lateinit var repository: MyRepository
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // repository готова к использованию
        repository.fetchData()
    }
}

Сводная таблица подходов

ПодходАннотация FragmentАннотация ActivityКомментарии
Dagger Hilt@AndroidEntryPoint@AndroidEntryPointСовременный рекомендуемый подход
Dagger AndroidНаследование от DaggerFragmentНаследование от DaggerAppCompatActivityУстаревший, но поддерживаемый
Ручная интеграцияБез аннотацийБез аннотацийПолный контроль, но больше boilerplate кода

Итог: Для новых проектов используйте @AndroidEntryPoint с Dagger Hilt — это наиболее эффективный и поддерживаемый подход, который минимизирует boilerplate код и корректно работает с жизненным циклом Android компонентов.