Projet : application Forage

1. Avant de commencer

Cet atelier de programmation présente une nouvelle application appelée Forage, que vous allez créer vous-même. Il explique les différentes étapes à suivre pour mener à bien le projet d'application Forage, y compris sa configuration et ses tests dans Android Studio.

Conditions préalables

  • Ce projet est destiné aux élèves qui ont terminé le module 5 du cours "Principes de base d'Android en Kotlin".

Objectifs de l'atelier

  • Ajoutez une persistance à une application existante avec Room en implémentant une entité, un DAO, un ViewModel et une classe de base de données.

Ce dont vous avez besoin

  • Un ordinateur sur lequel est installé Android Studio

2. Présentation de l'application terminée

L'application Forage, une fois terminée, permet aux utilisateurs de garder une trace des produits (alimentaires, par exemple) qu'ils ont trouvés dans la nature. Ces données sont conservées d'une session à l'autre à l'aide de Room. Vous utiliserez vos connaissances sur Room et sur les opérations de lecture, d'écriture, de mise à jour et de suppression effectuées sur une base de données pour implémenter la notion de persistance dans l'application Forage. L'application terminée et ses fonctionnalités sont décrites ci-dessous.

Lorsque l'application est lancée pour la première fois, l'utilisateur arrive sur un écran vide contenant une vue recycleur qui affiche les éléments rencontrés. En bas à droite de l'écran se trouve un bouton flottant permettant d'ajouter de nouveaux éléments.

3edd87e63c387d88.png

Lorsqu'un élément est ajouté, l'utilisateur peut saisir un nom, un emplacement et ajouter des notes supplémentaires. Une case à cocher permet d'indiquer si l'aliment est de saison.

6c0c739569bb3b4f.png

Une fois qu'un élément a été ajouté, il apparaît dans la vue recycleur sur le premier écran.

bcc75e60b70320e8.png

Lorsque vous appuyez sur un élément, un écran détaillé s'affiche avec son nom, son emplacement et des notes.

5096995a4921dcac.png

Le bouton flottant se transforme, passant du symbole "plus" à une icône d'édition. Appuyez sur ce bouton pour accéder à un écran qui vous permet de modifier le nom, le lieu, les notes et la case "de saison". Appuyez sur le bouton "Supprimer" pour supprimer l'élément de la base de données.

f8c708fed3dede1a.png

Bien que la partie UI de cette application ait déjà été implémentée, votre tâche consiste à implémenter la persistance en utilisant vos connaissances de Room, afin que l'application lise, écrive, mette à jour et supprime des éléments de la base de données.

3. Premiers pas

Télécharger le code du projet

Notez que le nom du dossier est android-basics-kotlin-forage-app. Sélectionnez ce dossier lorsque vous ouvrez le projet dans Android Studio.

Pour obtenir le code de cet atelier de programmation et l'ouvrir dans Android Studio, procédez comme suit :

Obtenir le code

  1. Cliquez sur l'URL indiquée. La page GitHub du projet s'ouvre dans un navigateur.
  2. Sur la page GitHub du projet, cliquez sur le bouton Code pour afficher une boîte de dialogue.

5b0a76c50478a73f.png

  1. Dans la boîte de dialogue, cliquez sur le bouton Download ZIP (Télécharger le fichier ZIP) pour enregistrer le projet sur votre ordinateur. Attendez la fin du téléchargement.
  2. Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
  3. Double-cliquez sur le fichier ZIP pour le décompresser. Un dossier contenant les fichiers du projet est alors créé.

Ouvrir le projet dans Android Studio

  1. Lancez Android Studio.
  2. Dans la fenêtre Welcome to Android Studio (Bienvenue dans Android Studio), cliquez sur Open an existing Android Studio project (Ouvrir un projet Android Studio existant).

36cc44fcf0f89a1d.png

Remarque : Si Android Studio est déjà ouvert, sélectionnez l'option de menu File > New > Import Project (Fichier > Nouveau > Importer un projet).

21f3eec988dcfbe9.png

  1. Dans la boîte de dialogue Import Project (Importer un projet), accédez à l'emplacement du dossier du projet décompressé. Il se trouve probablement dans le dossier Téléchargements.
  2. Double-cliquez sur le dossier de ce projet.
  3. Attendez qu'Android Studio ouvre le projet.
  4. Cliquez sur le bouton Run (Exécuter) 11c34fc5e516fb1c.png pour créer et exécuter l'application. Assurez-vous qu'elle fonctionne correctement.
  5. Parcourez les fichiers du projet dans la fenêtre de l'outil Projet pour voir comment l'application est configurée.

4. Configurer le projet pour utiliser Room

Définir l'entité "Forageable"

Le projet comporte déjà une classe Forageable qui définit les données de l'application (model.Forageable.kt). Cette classe possède plusieurs propriétés : id, name, address, inSeason et notes.

data class Forageable(
   val id: Long = 0,
   val name: String,
   val address: String,
   val inSeason: Boolean,
   val notes: String?
)

Toutefois, pour utiliser cette classe afin de stocker des données permanentes, vous devez la convertir en une entité Room.

  1. Annotez la classe en utilisant @Entity avec le nom de la table "forageable_database".
  2. Définissez la propriété id comme étant la clé primaire. La clé primaire devrait être générée automatiquement.
  3. Définissez le nom de colonne de la propriété inSeason sur "in_season".

Implémenter le DAO

ForageableDao (data.ForageableDao.kt), comme vous pouvez l'imaginer, permet de définir les méthodes de lecture et d'écriture depuis la base de données auxquelles vous accéderez à partir du modèle de visualisation. Étant donné que le DAO n'est qu'une interface que vous définissez, vous n'aurez pas à écrire de code pour implémenter ces méthodes. Vous devrez utiliser des annotations Room, en spécifiant la requête SQL si nécessaire.

Dans l'interface ForageableDao, ajoutez cinq méthodes.

  1. Une méthode getForageables() qui renvoie un Flow<List<Forageable>> pour toutes les lignes de la base de données.
  2. Une méthode getForageable(id: Long) qui renvoie un Flow<Forageable> correspondant à l'id spécifié.
  3. Une méthode insert(forageable: Forageable) qui introduit un nouveau Forageable dans la base de données.
  4. Une méthode update(forageable: Forageable) qui utilise un Forageable existant comme paramètre et qui met à jour la ligne en conséquence.
  5. Une méthode delete(forageable: Forageable) qui utilise un Forageable comme paramètre et le supprime de la base de données.

Implémenter le modèle de visualisation

Le ForageableViewModel (ui.viewmodel.ForageableViewModel.kt) est partiellement implémenté, mais vous devrez ajouter une fonctionnalité qui accède aux méthodes DAO afin d'autoriser la lecture et l'écriture de données. Pour implémenter ForageableViewModel, procédez comme suit :

  1. Une instance de ForageableDao doit être transmise en tant que paramètre dans le constructeur de la classe.
  2. Créez une variable de type LiveData<List<Forageable>> qui récupère la liste complète des entités Forageable à l'aide du DAO et qui convertit le résultat en LiveData.
  3. Créez une méthode qui utilise un ID (de type Long) comme paramètre et renvoie un LiveData<Forageable> qui appelle la méthode getForageable() sur le DAO, et qui convertit le résultat en LiveData.
  4. Dans la méthode addForageable(), lancez une coroutine à l'aide de viewModelScope et utilisez le DAO pour insérer l'instance Forageable dans la base de données.
  5. Dans la méthode updateForageable(), utilisez le DAO pour mettre à jour l'entité Forageable.
  6. Dans la méthode deleteForageable(), utilisez le DAO pour mettre à jour l'entité Forageable.
  7. Implémentez un ViewModelFactory pouvant créer une instance de ForageableViewModel avec un paramètre constructeur ForageableDao.

Implémenter la classe Database

La classe ForageDatabase (data.ForageDatabase.kt) permet de partager vos entités et votre DAO avec Room. Implémentez la classe ForageDatabase comme expliqué.

  1. Entités : Forageable
  2. Version : 1
  3. exportSchema : false
  4. Dans la classe ForageDatabase, incluez une fonction abstraite pour renvoyer un ForageableDao
  5. Dans la classe ForageDatabase, définissez un objet compagnon avec une variable privée appelée INSTANCE et une fonction getDatabase() qui renvoie le singleton ForageDatabase.
  1. Dans la classe BaseApplication, créez une propriété database qui renvoie une instance ForageDatabase à l'aide de l'initialisation différée.

5. Persister et lire les données des fragments

Une fois que vous avez configuré vos entités, le DAO, le modèle de visualisation et défini la classe de base de données pour les partager avec Room, il vous suffit de modifier les fragments pour accéder au modèle de visualisation. Vous devez modifier trois fichiers, un pour chaque écran de l'application.

Liste des aliments

L'écran de la liste des aliments ne nécessite que deux éléments : une référence au modèle de visualisation et un accès à la liste complète des aliments. Effectuez les tâches suivantes dans ui.ForageableListFragment.kt.

  1. La classe possède déjà une propriété viewModel. Toutefois, la classe "Factory" définie à l'étape précédente n'est pas utilisée. Vous devez d'abord refactoriser cette déclaration pour utiliser ForageableViewModelFactory.
private val viewModel: ForageableViewModel by activityViewModels {
   ForageableViewModelFactory(
       (activity?.application as BaseApplication).database.foragableDao()
   )
}
  1. Ensuite, dans onViewCreated(), observez la propriété allForageables de viewModel et appelez submitList() sur l'adaptateur, le cas échéant, pour remplir la liste.

Écran des détails des aliments

Reproduisez cette procédure pour la liste détaillée dans ui/ForageableDetailFragment.kt.

  1. Convertissez la propriété viewModel pour initialiser correctement ForageableViewModelFactory.
  2. Dans onViewCreated(), appelez getForageable() sur le modèle de visualisation pour transmettre l'id et obtenir l'entité Forageable. Observez les données en direct et définissez le résultat sur la propriété forageable, puis appelez bindForageable() pour mettre à jour l'interface utilisateur.

Écran "Ajouter et modifier des aliments"

Pour finir, vous devez faire la même chose dans ui.AddForageableFragment.kt. Notez que cet écran sert aussi à la mise à jour et à la suppression des entités. Toutefois, ces méthodes du modèle de visualisation sont déjà appelées au bon endroit. Vous ne devrez apporter que deux modifications à ce fichier.

  1. Là encore, refactorisez la propriété viewModel pour utiliser ForageableViewModelFactory.
  2. Dans onViewCreated(), dans le bloc "if" avant de définir la visibilité du bouton de suppression, appelez getForageable() sur le modèle de visualisation pour transmettre l'id et définir le résultat sur la propriété forageable.

C'est tout ce que vous avez à faire au niveau des fragments. Vous pouvez maintenant exécuter votre application et voir toutes les fonctionnalités de persistance en action.

6. Instructions de test

Exécuter vos tests

Pour exécuter les tests, vous pouvez effectuer l'une des opérations suivantes.

Pour un scénario de test unique, ouvrez une classe de scénario de test PersistenceInstrumentationTests.kt et cliquez sur la flèche verte à gauche de la déclaration de classe. Vous pouvez ensuite sélectionner l'option "Run" (Exécuter) dans le menu. Tous les tests seront exécutés dans le scénario de test.

3e640ec727599a6d.png

Souvent, il suffit d'exécuter un seul test, par exemple lorsqu'un test a échoué et que tous les autres ont réussi. Il est possible d'exécuter un seul test de la même manière que vous le feriez pour un scénario de test complet. Utilisez la flèche verte et sélectionnez l'option Exécuter.

8647a76419540499.png

Si vous avez plusieurs scénarios de test, vous pouvez également exécuter l'ensemble de la suite de tests. Comme pour l'exécution de l'application, cette option se trouve dans le menu Exécuter.

7a925c5e196725bb.png

Notez qu'Android Studio utilise par défaut la dernière cible que vous avez exécutée (applications, cibles de test, etc.). Par conséquent, si le menu indique toujours Run > Run 'app' (Exécuter > Exécuter 'application'), vous pouvez exécuter la cible de test en sélectionnant Run > Run (Exécuter > Exécuter).

90d3ec5ca5928b2a.png

Sélectionnez ensuite la cible de test dans le menu pop-up.

3b1a7d82a55b5f13.png