Aller au contenu

Créer le ViewModel

7.1 Qu'est-ce qu'un ViewModel ?

Le rôle de la ViewModel est de fournir des données à l'interface utilisateur et de survivre aux changements de configuration. Une ViewModel agit comme un centre de communication entre le Repository et l'interface utilisateur. Vous pouvez également utiliser une ViewModel pour partager des données entre des fragments. La ViewModel est une partie de la bibliothèque Lifecycle.

ViewModel diagram 1

ViewModel diagram 2

Pour une introduction à ce sujet, consultez ViewModel Overview ou le billet de blog ViewModels: A Simple Example.

7.2 Pourquoi utiliser un ViewModel ?

Un ViewModel conserve les données de l'interface utilisateur de votre application de manière consciente du cycle de vie, ce qui leur permet de survivre aux changements de configuration. Séparer les données de l'interface utilisateur de votre application de vos classes Activity et Fragment vous permet de mieux suivre le principe de responsabilité unique : vos activités et fragments sont responsables de l'affichage des données à l'écran, tandis que votre ViewModel peut s'occuper de conserver et de traiter toutes les données nécessaires à l'interface utilisateur.

Dans le ViewModel, utilisez LiveData pour les données modifiables que l'interface utilisateur utilisera ou affichera. L'utilisation de LiveData présente plusieurs avantages :

  • Vous pouvez utiliser un observateur sur les données (au lieu de les interroger régulièrement) et mettre à jour l'interface utilisateur uniquement lorsque les données changent réellement.
  • Le référentiel (Repository) et l'interface utilisateur sont complètement séparés par le ViewModel.
  • Il n'y a pas d'appels à la base de données depuis le ViewModel (tout cela est géré dans le référentiel), ce qui rend le code plus testable.

7.3 Implémenter le ViewModel

Créez un fichier de classe pour WordViewModel sous la racine du package de votre application et ajoutez-y ce code :

WordViewModel.kt
class WordViewModel(application: Application) : AndroidViewModel(application) {

    private val repository = WordRepository(WordRoomDatabase.getDatabase(application).wordDao())

    val allWords: LiveData<List<Word>> = repository.allWords

    // Lance l'insertion dans une coroutine liée au cycle de vie du ViewModel.
    fun insert(word: Word) {
        viewModelScope.launch {
            repository.insert(word)
        }
    }
}

Explications :

  • Créé une classe appelée WordViewModel qui prend l'application comme paramètre et étend AndroidViewModel.
  • Ajouté une propriété privée repository pour conserver une référence au dépôt, créé à partir du DAO de la base de données.
  • Ajouté une propriété allWords pour exposer la liste de mots en cache : elle est initialisée avec le LiveData du dépôt.
  • Créé une fonction wrapper insert() qui appelle la fonction insert() du dépôt. De cette façon, l'implémentation de insert() est encapsulée de l'interface utilisateur.
  • viewModelScope.launch { ... } lance une coroutine pour appeler la fonction suspend du dépôt. Le viewModelScope est lié au cycle de vie du ViewModel : les coroutines en cours sont annulées automatiquement lorsque le ViewModel est détruit (appel de onCleared()).

Attention aux fuites de mémoire

Ne conservez pas de référence à un contexte dont le cycle de vie est plus court que celui de votre ViewModel ! Des exemples sont :

  • Activité
  • Fragment
  • Vue

Conserver une référence peut provoquer une fuite de mémoire, par exemple si le ViewModel a une référence à une Activity détruite. Tous ces objets peuvent être détruits par le système d'exploitation et recréés lors d'un changement de configuration, ce qui peut se produire plusieurs fois pendant le cycle de vie d'un ViewModel.

Si vous avez besoin du contexte de l'application (qui a un cycle de vie aussi long que celui de l'application), utilisez AndroidViewModel, comme indiqué dans ce codelab.

Persistance des données

Les **ViewModel**s ne survivent pas à l'arrêt du processus de l'application en arrière-plan lorsque le système d'exploitation a besoin de plus de ressources. Pour les données de l'interface utilisateur qui doivent survivre à la mort du processus due à un manque de ressources, vous pouvez utiliser le module Saved State pour les ViewModels. En savoir plus ici.

Ressources complémentaires

Pour en savoir plus sur les classes ViewModel, regardez la vidéo Architecture Components: ViewModel.