Utiliser Hilt avec d'autres bibliothèques Jetpack

Hilt comprend des extensions permettant de fournir des classes issues d'autres bibliothèques Jetpack. Actuellement, Hilt prend en charge les composants Jetpack suivants :

  • Nouveau message
  • ViewModel
  • Navigation
  • WorkManager

Vous devez ajouter les dépendances de Hilt pour bénéficier de ces intégrations. Pour en savoir plus sur l'ajout de dépendances, consultez la section Injection de dépendances avec Hilt.

Intégration à Jetpack Compose

Pour découvrir l'intégration de Hilt à Jetpack Compose, consultez la section sur Hilt de Compose et autres bibliothèques.

Injecter des objets ViewModel avec Hilt

Fournissez un ViewModel en l'annotant avec @HiltViewModel et en utilisant l'annotation @Inject dans le constructeur de l'objet ViewModel.

@HiltViewModel
class ExampleViewModel @Inject constructor(
  private val savedStateHandle: SavedStateHandle,
  private val repository: ExampleRepository
) : ViewModel() {
  ...
}

Ensuite, une activité annotée avec @AndroidEntryPoint peut obtenir l'instance ViewModel comme d'habitude en utilisant ViewModelProvider ou les extensions KTX de by viewModels() :

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
  private val exampleViewModel: ExampleViewModel by viewModels()
  ...
}

Utiliser l'injection assistée avec les ViewModels

Hilt est compatible avec l'injection assistée pour les ViewModels. L'injection assistée vous permet d'injecter des arguments d'exécution dynamiques en plus des dépendances gérées par Hilt. Pour utiliser l'injection assistée, annotez votre constructeur ViewModel avec @AssistedInject et marquez les paramètres dynamiques avec @Assisted. Vous devez également définir une interface @AssistedFactory, qui sert de pont pour que Hilt génère automatiquement le @ViewModelProvider.Factory nécessaire.

@HiltViewModel(assistedFactory = MyViewModel.Factory::class)
class MyViewModel @AssistedInject constructor(
    @Assisted val userId: String,
    private val repository: MyRepository
) : ViewModel() {
    @AssistedFactory interface Factory {
        fun create(userId: String): MyViewModel
    }
}

Dans Compose, vous pouvez utiliser la fabrique assistée en la transmettant à la fonction hiltViewModel lors de la navigation ou de l'initialisation de l'écran. Cette approche élimine le besoin d'un code récurrent d'usine manuel tout en conservant votre ViewModel correctement limité à la pile de retour de navigation. Pour en savoir plus, consultez la documentation Hilt sur l'injection assistée.

"@ViewModelScoped"

Tous les ViewModels de Hilt sont fournis par le ViewModelComponent, qui suit le même cycle de vie qu'un ViewModel. Par conséquent, ils peuvent survivre aux changements de configuration. Pour définir le champ d'application d'une dépendance sur un ViewModel, utilisez l'annotation @ViewModelScoped.

Avec le type @ViewModelScoped, une seule instance du type limité est fournie pour toutes les dépendances injectées dans le ViewModel. Les autres instances d'un ViewModel qui demandent l'instance limitée recevront une autre instance.

Si une seule instance doit être partagée entre différents ViewModels, son champ d'application doit être défini à l'aide de @ActivityRetainedScoped ou de @Singleton.

Intégration aux bibliothèques de navigation Jetpack

Ajoutez les dépendances supplémentaires suivantes à votre fichier Gradle :

app/build.gradle

Kotlin

dependencies {
    ...
    implementation("androidx.hilt:hilt-lifecycle-viewmodel-compose:1.3.0")
}

Groovy

dependencies {
    ...
    implementation 'androidx.hilt:hilt-lifecycle-viewmodel-compose:1.3.0'
}

Dans Jetpack Compose, les bibliothèques Navigation Compose et Navigation 3 utilisent toutes deux la fonction hiltViewModel pour récupérer automatiquement un ViewModel limité à la destination de navigation actuelle.

Dans Navigation 3, les destinations de navigation sont représentées par des NavEntry. Limitez le champ d'application des ViewModels aux NavEntry à l'aide de rememberViewModelStoreNavEntryDecorator. Utilisez hiltViewModel dans le fournisseur de ce NavEntry pour récupérer le ViewModel associé.

NavDisplay(...,
  entryDecorators = listOf(..., rememberViewModelStoreNavEntryDecorator()),
  entryProvider = entryProvider {
    entry { key ->
      val viewModel = hiltViewModel()
      MyScreen(viewModel = viewModel)
    }
  }
)

Dans Navigation Compose, les ViewModels sont automatiquement limités aux destinations de navigation. Pour en savoir plus, consultez Hilt et Navigation.

val viewModel = hiltViewModel()

Injecter WorkManager avec Hilt

Ajoutez les dépendances supplémentaires suivantes à votre fichier Gradle. Notez qu'en plus de la bibliothèque, vous devez inclure un processeur d'annotations supplémentaire qui fonctionne avec le processeur d'annotations Hilt :

app/build.gradle

Kotlin

dependencies {
    implementation("androidx.hilt:hilt-work:1.0.0")
    // When using Kotlin.
    ksp("androidx.hilt:hilt-compiler:1.4.0")
}

Groovy

dependencies {
  ...
  implementation 'androidx.hilt:hilt-work:1.0.0'
  // When using Kotlin.
  ksp 'androidx.hilt:hilt-compiler:1.4.0'
}

Injectez un Worker à l'aide de l'annotation @HiltWorker dans la classe et de @AssistedInject dans le constructeur de l'objet Worker. Vous pouvez utiliser uniquement @Singleton ou des liaisons sans champ d'application dans les objets Worker. Vous devez également annoter les dépendances Context et WorkerParameters avec @Assisted :

@HiltWorker
class ExampleWorker @AssistedInject constructor(
  @Assisted appContext: Context,
  @Assisted workerParams: WorkerParameters,
  workerDependency: WorkerDependency
) : Worker(appContext, workerParams) { ... }

Ensuite, faites en sorte que votre classe Application implémente l'interface Configuration.Provider, injecte une instance de HiltWorkFactory et la transmette dans la configuration WorkManager, comme suit :

@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {

  @Inject lateinit var workerFactory: HiltWorkerFactory

  override fun getWorkManagerConfiguration() =
      Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}