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 constructaire 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 by viewModels() extensions KTX :

@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 le constructeur de votre 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 de code passe-partout manuel pour la fabrique tout en conservant le champ d'application correct de votre ViewModel dans 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. Définissez le champ d'application des ViewModels sur les NavEntrys à l'aide de rememberViewModelStoreNavEntryDecorator. Utilisez hiltViewModel dans le fournisseur pour que NavEntry récupère 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.3.0")
}

Groovy

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

Injectez un Worker à l'aide de l' @HiltWorker annotation dans la classe et @AssistedInject dans le Worker constructeur de l'objet. 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 Application classe 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()
}