Créer des ViewModels avec des dépendances   Inclus dans Android Jetpack.

Conformément aux bonnes pratiques sur l'injection de dépendances, les ViewModels peuvent utiliser des dépendances comme paramètres dans leur constructeur. Il s'agit principalement de types issus des couches de domaines ou de données. Comme le framework fournit les ViewModels, un mécanisme spécial est nécessaire pour en créer des instances. Ce mécanisme correspond à l'interface ViewModelProvider.Factory. Seules les implémentations de cette interface peuvent instancier les ViewModels avec le champ d'application approprié.

ViewModels avec CreationExtras

Si une classe ViewModel reçoit des dépendances dans son constructeur, fournissez une fabrique qui implémente l'interface ViewModelProvider.Factory. Remplacez la fonction create(Class<T>, CreationExtras) pour fournir une nouvelle instance du ViewModel.

CreationExtras vous permet d'accéder à des informations pertinentes pour instancier un ViewModel. Voici une liste de clés accessibles depuis Extras :

Clé Fonctionnalité
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY Fournit l'accès à la clé personnalisée que vous avez transmise à ViewModelProvider.get().
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY Fournit l'accès à l'instance de la classe Application.
SavedStateHandleSupport.DEFAULT_ARGS_KEY Fournit l'accès au bundle d'arguments à utiliser pour construire SavedStateHandle.
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY Fournit l'accès au SavedStateRegistryOwner utilisé pour créer le ViewModel.
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY Fournit l'accès au ViewModelStoreOwner utilisé pour créer le ViewModel.

Pour créer une instance de SavedStateHandle, utilisez la fonction CreationExtras.createSavedStateHandle() et transmettez-la au ViewModel.

CreationExtras avec APPLICATION_KEY

L'exemple suivant montre comment fournir une instance d'un ViewModel qui utilise un dépôt limité à la classe Application et à SavedStateHandle en tant que dépendances :

    import androidx.lifecycle.SavedStateHandle
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.ViewModelProvider
    import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
    import androidx.lifecycle.createSavedStateHandle
    import androidx.lifecycle.viewmodel.initializer
    import androidx.lifecycle.viewmodel.viewModelFactory

    class MyViewModel(
        private val myRepository: MyRepository,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {

        // ViewModel logic
        // ...

        // Define ViewModel factory in a companion object
        companion object {

            val Factory: ViewModelProvider.Factory = viewModelFactory {
                initializer {
                    val savedStateHandle = createSavedStateHandle()
                    val myRepository = (this[APPLICATION_KEY] as MyApplication).myRepository
                    MyViewModel(
                        myRepository = myRepository,
                        savedStateHandle = savedStateHandle
                    )
                }
            }
        }
    }

Vous pouvez ensuite utiliser cette fabrique pour récupérer une instance du ViewModel :

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    modifier: Modifier = Modifier,
    viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
    // ...
}

Transmettre des paramètres personnalisés en tant que CreationExtras

Vous pouvez transmettre des dépendances à votre ViewModel via CreationExtras en créant une clé personnalisée. Cela peut être utile si votre ViewModel dépend d'objets qui ne sont pas accessibles via la classe Application et APPLICATION_KEY. Par exemple, lorsque votre ViewModel est créé dans un module Kotlin Multiplatform et n'a donc pas accès aux dépendances Android.

Dans cet exemple, ViewModel définit une clé personnalisée et l'utilise dans ViewModelProvider.Factory.

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory

class MyViewModel(
    private val myRepository: MyRepository,
) : ViewModel() {
    // ViewModel logic

    // Define ViewModel factory in a companion object
    companion object {

        // Define a custom key using the factory function
        val MY_REPOSITORY_KEY = CreationExtras.Key<MyRepository>()

        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                // Get the dependency in your factory
                val myRepository = this[MY_REPOSITORY_KEY] as MyRepository
                MyViewModel(
                    myRepository = myRepository,
                )
            }
        }
    }
}

Vous pouvez instancier un ViewModel avec un CreationExtras.Key directement dans vos composables.

import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
// ...
@Composable
fun MyApp(myRepository: MyRepository) {
    val extras = MutableCreationExtras().apply {
        set(MyViewModel.MY_REPOSITORY_KEY, myRepository)
    }
    val viewModel: MyViewModel = viewModel(
        factory = MyViewModel.Factory,
        extras = extras,
    )
}

Ressources supplémentaires

Pour en savoir plus sur les ViewModels et les dépendances, consultez les ressources supplémentaires suivantes :

Documentation

Afficher le contenu