Android Architecture Components - Mise en pratique (Part 6 - ViewModel / LiveData)

Ceci est la 6ème partie d'un lot de 7 tutoriels.

Vous pouvez repartir de l'étape précédente ou tirer la solution contenue dans le commit 5-Fuel

La solution est disponible sur le commit 6-ViewModel_LiveData

Rappels

Rappelons brièvement pourquoi nous allons utiliser ViewModel et LiveData.

ViewModel

ViewModel résout les problèmes de changement d'orientation. Un passage de portrait à paysage conduit à la recréation de l'activité affichée. Toute donnée non sauvegardée sera donc perdue.

ViewModel possède un cycle de vie particulier. Il s'exécute en parallèle des Activités. En revanche, il n'est pas détruit en cas d'événements du type changement d'orientation. Il est donc parfait dans un rôle de data holder pour une Activité / un Fragment / etc.

LiveData

LiveData est un data wrapper lifecycle-aware. C'est à dire qu'il observe l'état du composant auquel il est attaché. Ainsi, il transmettra sa donnée à son propriétaire que s'il est en mesure de le recevoir. Par exemple, une activité recevra de la data que si elle est visible et au premier plan.

Ajout des dépendances

Ajouter dans app/build.gradle :

lifecycle-extensions comprend :

  • ViewModel
  • LiveData
  • LifeCycle

Création du ViewModel

Créer dans un nouveau package vm une classe CoinViewModel :

CoinViewModel ici a un double rôle :

  • Service, puisque c'est ici qu'on réalise l'appel à coinmarket
  • Data Holder, via la variable d'instance coins

Nous annotons le primary constructor de CoinViewModel avec @Inject. C'est parce qu'il sera initialisé via injection de dépendances dans MainActivity.

Cette annotation permet aussi d'injecter coinsResultDeserializer. Nous le pouvons grâce à notre configuration Dagger dans AppModule (cf l'article précédent) :

Dans ce contexte, nous souhaitons aussi avoir une unique instance de ViewModel. Une solution possible est l'annotation de la classe avec @Singleton.

Mise à jour de l'Activité

Reprendre MainActivity et la modifier :

Premier point à noter, l'injection de CoinViewModel :

Ensuite, dans la fonction init(), la définition d'un pattern observer :

Attardons-nous sur la méthode observe(LifecycleOwner owner, Observer observer) :

  • Le premier paramètre est un LifecycleOwner. C'est l'objet que va observer LiveData. Nous passons this puisque AppCompatActivity, le parent de MainActivity, est un LifecycleOwner natif.
  • Le second paramètre est un Observer. Il définit le callback de LiveData. Il est déclenché à chaque changement des données. Nous passons la variable d'instance updateCoins. En fait, elle est équivalente à la fonction fetchCoins() de l'étape précédente. La fonction refreshCoinsList(newCoins: Array) était auparavant refreshCoins. Ce renommage n'est pas anodin. Le but est d'être encore plus précis sur ce que font ces deux blocs de code.

Conclusion

Nous ajoutons progressivement des fonctionnalités à notre application. Malgré le nombre de briques qui augmente, le code est de plus en plus épuré. Le fichier le plus long reste notre activité...en ayant moins de 80 lignes de code ! La prochaine et dernière étape sera consacrée à la création d'un cache.

Sources