Database Views avec Room pour Android

Room est une couche d’abstraction sur SQLite que Google a emballé comme une bibliothèque AndroidX et recommande également. Depuis la version 2.1, Room offre la possibilité d’ajouter des Database Views, également connues sous le nom de requêtes stockées.

Certaines des bonnes raisons d’utiliser les Database Views seraient :

  • Elles vous permettent d’écrire facilement des requêtes complexes et de les utiliser dans des requêtes DAO (Data Access Object).
  • Vous pouvez interroger uniquement les champs dont vous avez besoin, plutôt que de devoir passer par tous les champs d’une table.

Dans ce tutoriel, vous allez construire une application de sondages clients qui permet aux clients d’un restaurant de laisser des commentaires, puis d’enregistrer ces commentaires dans la base de données gérée par Room. Au cours du processus, vous apprendrez ce qui suit :

  • Qu’est-ce qu’une vue de base de données ?
  • Comment créer des vues de base de données ?
  • Comment les utiliser pour simplifier l’écriture de requêtes SELECT
Remarque : Ce tutoriel suppose que vous avez de l’expérience dans le développement pour Android en Kotlin et que vous avez déjà travaillé avec Room. Si vous n’êtes pas familier avec Room, jetez un œil à notre tutoriel Persistance des données avec Room.

Ce tutoriel utilise également les Coroutines avec Room. Pour en savoir plus, lisez notre tutoriel Coroutines avec la bibliothèque de persistance Room.

Mise en route

Téléchargez le projet de démarrage en cliquant sur le bouton Télécharger le matériel en haut ou en bas de ce tutoriel.

Extractez le fichier ZIP et ouvrez le projet de démarrage dans Android Studio 4.0 ou plus en sélectionnant Ouvrir un projet Android Studio existant dans l’écran de bienvenue.

Une fois la synchronisation Gradle terminée, explorez la structure du projet. Le projet suit l’architecture MVVM, donc les fonctionnalités similaires sont sous un seul paquet. Familiarisez-vous avec les packages présents – vous les utiliserez dans ce tutoriel.

Construisez et exécutez. Vous verrez un écran simple avec un message de bienvenue, une image et un bouton START SURVEY.

Écran de démarrage de l'application Enquêtes clients

Touchez le bouton DEMARRER L’ENQUÊTE. Pour les besoins de ce tutoriel, vous pouvez ignorer le fait que vous n’avez pas mangé un repas au restaurant. :]

L’écran suivant est celui du sondage. Il comporte un champ de saisie d’email, des boutons radio pour choisir le repas que vous évaluez et trois questions. Chaque question a des boutons Bon, Moyen et Mauvais en dessous, afin que l’utilisateur puisse évaluer sa satisfaction.

L'écran d'enquête de l'application Customer Surveys avec les questions et les évaluations possibles

Vous verrez également le bouton SUBMIT SURVEY. Appuyez dessus et vous verrez un toast qui indique qu’il n’est pas encore temps de répondre à l’enquête. Ne vous inquiétez pas, vous réparerez cela au cours de ce tutoriel.

Vous avez maintenant été accueilli au restaurant The View, où vous pourrez voir des vues incroyables de la nature, goûter leurs délicieux repas et évaluer votre satisfaction. Pendant ce temps, vous apprendrez également à connaître les vues de base de données Room.

Utilisation des vues de base de données

Considérez une table qui a une fonctionnalité supplémentaire de requêtes SELECT pré-packagées pour la commodité. Room version 2.1 et plus appelle cela comme une vue de base de données et fournit une annotation avec le même nom c’est-à-dire @DatabaseView.

En utilisant cette annotation, vous pouvez marquer une classe pour qu’elle se comporte comme une vue de base de données. Cela vous permettra d’attacher une requête à la classe, comme ci-dessous :

@DatabaseView("SELECT user.id, user.name " + "AS departmentName FROM user " + "WHERE user.departmentId = department.id")class User { var id: Long = 0 var name: String? = null}

Vous pouvez ensuite utiliser cette classe dans votre DAO pour interroger des données de la même manière que vous le feriez avec une classe marquée comme une entité, c’est-à-dire une table dans une base de données.

Un DAO vous aide à accéder aux données de la base de données de votre application. Il contient généralement les méthodes CUD (Create, Update and Delete) et peut également contenir d’autres méthodes qui peuvent être nécessaires pour l’accès en lecture et en écriture à la base de données.

La relation entre les Database Views et la base de données est similaire à la relation entre les entités et la base de données. Vous examinerez ces relations plus en profondeur la prochaine fois.

Comparaison entre une vue de base de données et une entité

Les classes annotées avec @DatabaseView sont similaires aux classes Entity. Voici comment :

  • Elles peuvent toutes deux utiliser SELECT FROM dans les requêtes DAO.
  • Database Views et Entitys peuvent toutes deux utiliser @ColumnInfo, qui permet de personnaliser les informations de colonne associées à un champ.
  • Elles peuvent toutes deux utiliser @Embedded, qui permet à un champ d’avoir des champs imbriqués que les requêtes peuvent référencer directement.

Bien qu’il existe de nombreuses similitudes entre les deux, il existe également des différences entre les DatabaseView et les Entity:

  • Vous pouvez utiliser INSERT, UPDATE et DELETE avec un Entity, mais pas avec un DatabaseView.
  • Vous définissez toutes vos vues dans vos apps en utilisant views, mais vous définissez les entités en utilisant entities.

Maintenant que vous savez ce qu’est une DatabaseView et comment elle se compare et s’oppose à une classe Entity, il est temps de l’utiliser et de commencer à soumettre l’enquête pour Le restaurant de la vue.

Soumission du sondage

Votre première étape consiste à ajouter la logique pour soumettre le sondage et l’enregistrer dans la base de données Room après avoir appuyé sur le bouton SUBMIT SURVEY.

Naviguez vers customersurveys/CustomerSurveyFragment.kt, où vous ajouterez la logique pour collecter les réponses et les enregistrer dans Room. Faites-le en remplaçant le code dans submitSurvey() par ceci:

// 1val email = editEmail.text.toString()// 2if (validateEmail(email)) { // 3 val meal = when (radioGroupMeals.checkedRadioButtonId) { R.id.radioBreakfast -> "Breakfast" R.id.radioLunch -> "Lunch" R.id.radioDinner -> "Dinner" else -> "No Meal" } // 4 val customerSurvey = SurveyListItem .CustomerSurvey(0, email, meal, questionOneAnswer, questionTwoAnswer, questionThreeAnswer) customerSurveyViewModel.insertCustomerSurvey(customerSurvey) // 5 findNavController() .navigate(R.id.action_surveyFragment_to_surveyCompletedFragment)}

Voici ce que vous faites avec ce code:

  1. Vous obtenez le courriel de editEmail et l’assignez à une variable : email.
  2. Cette vérification de condition appelle validateEmail(email), qui vérifie si le courriel est null ou non. Il renvoie false si c’est null. Il vérifie également si le courriel saisi est valide et renvoie false s’il ne l’est pas.
  3. Le code à l’intérieur de l’instruction if s’exécute lorsque validateEmail(email) renvoie true. meal détient le type de repas que l’utilisateur a sélectionné dans les groupes radio.
  4. Une fois que vous avez la valeur de meal, vous créez SurveyListItem.CustomerSurvey, qui a toutes les informations sur l’enquête. Il tire les valeurs de questionOneAnswer, questionTwoAnswer et questionThreeAnswer de toggleButtonListeners(), qui a des écouteurs à cet effet.
  5. Ici, vous sauvegardez customerSurvey en appelant insertCustomerSurvey(customerSurvey) dans CustomerSurveyViewModel, qui gère la logique de sauvegarde dans la pièce.
  6. Vous naviguez vers SurveyCompletedFragment.

Après avoir ajouté ceci, vous remarquerez que customerSurveyViewModel et findNavController() sont soulignés en rouge. Pour corriger cela, ajoutez d’abord l’initialisation CustomerSurveyViewModel en haut de la classe, juste en dessous de l’initialisation questionThreeAnswer.

private val customerSurveyViewModel: CustomerSurveyViewModel by viewModels()

Assurez-vous d’ajouter les déclarations d’importation respectives lorsque l’IDE vous le demande.

Construisez et exécutez. Lancez l’enquête, saisissez l’entrée d’email requise et sélectionnez vos réponses aux questions.

Écran d'enquête avec les réponses

Génial, vous avez terminé l’enquête.

Voir toutes les enquêtes en utilisant les vues de la base de données Capture d'écran

Tapez sur le bouton VOIR LES ENQUÊTES… oups, cela ne fait rien encore. Ne vous inquiétez pas, vous allez corriger cela bientôt.

Dans la section suivante, vous apprendrez à créer votre première DatabaseView.

Création d’une vue de base de données

Pour créer une vue, vous ajouterez une annotation @DatabaseView à une classe ou une classe de données. Commencez par naviguer vers customersurveys/SurveyListItem.kt. C’est une classe scellée avec quelques classes de données que vous utiliserez dans ce tutoriel.

Au bas de SurveyListItem, juste en dessous de QuestionOneSadView, ajoutez ce qui suit :

data class HappyBreakFastView( override val email: String) : SurveyListItem()

Cette classe de données remplace la variable email de SurveyListItem et hérite de la classe – ce qui signifie qu’elle est un sous-type de SurveyListItem.

Après avoir créé cette classe de données, ajoutez @DatabaseView avec une requête SELECT pour récupérer tous les ids d’email de la table CustomerSurvey où le repas est défini sur « Breakfast », juste au-dessus de la classe de données HappyBreakFastView. Votre annotation devrait ressembler à ceci:

@DatabaseView("SELECT CustomerSurvey.email FROM CustomerSurvey WHERE CustomerSurvey.meal = 'Breakfast'")

Quelques choses à noter à propos de la requête à l’intérieur de l’annotation:

  • La requête fonctionne comme toute autre requête que vous avez écrite dans Room.
  • Vous devez demander tous les champs que vous avez dans votre classe de données lorsque vous écrivez la requête. Dans ce cas, vous n’avez besoin que de l’email. Vous utilisez SELECT CustomerSurvey.email From... pour obtenir l’email de CustomerSurvey.
Remarque : Pour ce tutoriel, vous gardez les vues et l’entité à l’intérieur de SurveyListItem pour éviter les répétitions et rendre le code plus facile à lire. Vous n’avez pas toujours besoin de sous-classer vos vues dans une classe scellée ; elles peuvent aussi être dans leur propre fichier ou classe séparé.

Félicitations, vous avez créé votre première vue ! Ensuite, vous allez voir comment vous pouvez utiliser la vue dans vos requêtes DAO.

Utilisation des vues de la base de données de la pièce dans les requêtes DAO

D’abord, vous allez inclure HappyBreakFastView dans views dans l’annotation @Databasede l’app.

Naviguez vers database/AppDatabase.kt et, à l’intérieur de views, ajoutez SurveyListItem.HappyBreakFastView::class. Votre annotation @Database mise à jour devrait ressembler à ce qui suit :

@Database(entities = , version = 2, exportSchema = false, views = )

Notez que le version = 2. Vous devez mettre à jour la version de la base de données chaque fois que vous ajoutez un view dans l’AppDatabase – sinon, votre application se plantera. Dans ce cas, vous avez mis à jour la version à 2. Synchronisez gradle pour appliquer tous ces changements.

Puis, naviguez vers customers/CustomerSurveysDao.kt et, juste en dessous de getQuestionOneSadView(), ajoutez le code suivant :

@Query("SELECT * FROM HappyBreakFastView")fun getHappyBreakFastCustomers():LiveData<List<SurveyListItem.HappyBreakFastView>>

Cette méthode récupère tous les clients qui ont été satisfaits de n’importe quel aspect de l’enquête du restaurant. Pour l’expliquer plus en détail :

  • D’abord, vous utilisez HappyBreakFastView comme vous le feriez dans une requête normale.
  • Vous appelez cette méthode dans CustomerSurveyRepo pour obtenir une liste de tous les clients qui ont répondu à l’une des questions avec Bien. Notez que le type de retour de la méthode est une liste LiveData de type SurveyListItem.HappyBreakFastView, qui est un support de variable observable.

Maintenant, vous avez créé un view et la méthode pour interroger la liste des clients qui ont répondu avec une réponse positive dans CustomerSurveysDao. Dans la section suivante, vous apprendrez comment appeler cette méthode à partir de la classe de dépôt.

Récupération de données à l’aide d’une DatabaseView

Naviguez vers customersurveys/CustomerSurveyRepo.kt et ajoutez la méthode suivante juste en dessous de getQuestionOneSadView():

fun getHappyBreakFastCustomers() : LiveData<List<SurveyListItem.HappyBreakFastView>> { return customerSurveysDao.getHappyBreakFastCustomers()}

Cette méthode appelle getHappyBreakFastCustomers() de CustomerSurveysDao pour obtenir les données de Room. Son type de retour est un LiveData, ce qui permet à l’appelant de cette méthode d’observer tout changement dans les données.

Puis, vous ajouterez un appel à getHappyBreakFastCustomers() dans CustomerSurveyViewModel. Il est responsable de l’affichage des données sur la vue – qui, dans ce cas, n’est pas DatabaseView mais AllSurveysFragment.

Naviguez vers customersurveys/CustomerSurveyViewModel.kt et ajoutez le code suivant :

val happyBreakfastCustomers : LiveData<List<SurveyListItem.HappyBreakFastView>> by lazy { customerSurveyRepo.getHappyBreakFastCustomers()}

Cette variable obtient sa valeur en appelant getHappyBreakFastCustomers() depuis CustomerSurveyRepo. Il y a un by lazy{} pour que vous ne chargiez pas les données immédiatement, mais plutôt lorsque la variable est accédée pour la première fois.

Puis, vous mettrez à jour l’interface utilisateur pour qu’elle puisse afficher les données.

Affichage des données sur l’interface utilisateur

Naviguez vers allsurveys/AllSurveysFragment.kt et ajoutez le code suivant au bas de la classe :

private fun getHappyBreakfastCustomers() { customerSurveyViewModel.happyBreakfastCustomers.observe(viewLifecycleOwner, Observer { customerSurveyList -> if (customerSurveyList.isEmpty()) { layoutEmptyView.visibility = View.VISIBLE rvReviews.visibility = View.GONE } else { layoutEmptyView.visibility = View.GONE rvReviews.visibility = View.VISIBLE initView(customerSurveyList) } })}private fun initView(customerSurveySurveyList: List<SurveyListItem.HappyBreakFastView>) { val customerSurveysAdapter = CustomerSurveysAdapter(customerSurveySurveyList) rvReviews.adapter = customerSurveysAdapter}

Pour expliquer ce que fait le code :

  • D’abord, il appelle happyBreakfastCustomers et observe sa valeur.
  • À l’intérieur de la lambda observe, il y a une vérification pour voir si customerSurveyList est null ou non. Si la liste est null, on met le message No surveys found ! de TextView à visible et on cache RecyclerView. Si elle n’est pas null, vous mettez la visibilité de TextView à GONE et affichez RecyclerView. Vous appelez également initView(customerSurveyList) avec la valeur customerSurveyList de CustomerSurveyViewModel.
  • initView(customerSurveySurveyList: List) initialise CustomerSurveysAdapter avec customerSurveyList et définit l’adaptateur pour RecyclerView à CustomerSurveysAdapter, qui affiche maintenant la liste des enquêtes à l’interface utilisateur.

L’IDE vous demandera d’ajouter l’importation SurveyListItem. S’il ne le fait pas, ajoutez cet import :

import com.raywenderlich.android.customersurveys.customersurveys.SurveyListItem

Maintenant que vous avez affiché les données à l’interface utilisateur, il ne vous reste que quelques étapes avant que tout fonctionne parfaitement.

Puis, vous ajouterez le code qui gère la récupération des données de Room en fonction de l’option sélectionnée sur la liste déroulante dans l’interface utilisateur c’est-à-dire le widget Spinner.

Recherche de données pour les différentes vues

Ajoutez le morceau de code suivant juste en dessous de onCreate dans AllSurveysFragment.kt::

private fun spinnerListener() { filterSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { when (position) { 0 -> resetState() 1 -> getAllCustomerSurveys() 2 -> getHappyBreakfastCustomers() 3 -> getSadDinnerCustomers() 4 -> getAverageLunchCustomers() 5 -> getQuestionOneSadCustomers() } } }}

Le morceau de code ci-dessus définit onItemSelectedListener à filterSpinner et surcharge deux méthodes : onNothingSelected et onItemSelected. Vous ne voulez rien faire lorsque rien n’est sélectionné, donc onNothingSelected est laissé vide. Vous voulez en revanche réagir lorsqu’un élément est sélectionné, vous devez donc implémenter onItemSelected.

onItemSelected possède une expression when qui appelle différentes méthodes en fonction de l’option sélectionnée dans filterSpinner. Ces méthodes sont similaires à getHappyBreakfastCustomers(), mais elles récupèrent les données en utilisant un DatabaseView différent.

Assurez-vous d’ajouter les importations lorsque l’IDE vous le demande.

Enfin, ajoutez un appel à spinnerListener() à l’intérieur de onViewCreated, juste après setupSpinner(), comme indiqué ci-dessous :

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupSpinner() // Added spinnerListener()}

Maintenant que vous avez tout préparé pour récupérer les enquêtes, votre prochaine étape consiste à ajouter le code pour naviguer vers AllSurveysFragment.

Naviguer vers toutes les enquêtes

C’est la dernière étape dont vous avez besoin pour voir les vues en action.

Naviguez vers completedsurvey/SurveyCompletedFragment.kt et décommentez le code à l’intérieur de btnViewSurveys. Votre résultat final ressemblera à ceci:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) btnViewSurveys.setOnClickListener { findNavController() .navigate(R.id.action_surveyCompletedFragment_to_allSurveysFragment) }}

Ici, vous définissez simplement l’écouteur de clic pour le bouton VIEW SURVEYS et naviguez vers AllSurveysFragment.

Une fois que vous décomposez le code, l’IDE vous demandera d’importer findNavController(). Il suffit d’importer le nécessaire.

Construire, exécuter et démarrer une enquête, puis répondre aux questions et les soumettre. Enfin, affichez Toutes les enquêtes, où vous pourrez récupérer toutes les données en fonction de l’option que vous avez sélectionnée sur le spinner.

Options du spinner dans l'app
Liste de clients moyennement heureux à l'aide d'une vue de base de données
Clients tristes du dîner non trouvés à l'aide d'une vue de base de données

Félicitations ! Vous avez terminé votre expérience au restaurant The View. Nous espérons que vous avez pris un excellent repas, vu des vues incroyables et eu la chance d’apprendre ce que sont les DatabaseViews.

Qu’est-ce qu’on fait maintenant ?

Téléchargez le projet final en utilisant le bouton Télécharger les matériaux en haut ou en bas du tutoriel.

Pour plus d’informations sur les fonctionnalités de Room, consultez la documentation officielle d’Android.

Nous espérons que vous avez apprécié ce tutoriel Room Database Views. Si vous avez des questions, des commentaires ou des modifications géniales à apporter à cette application de projet, veuillez rejoindre la discussion du forum ci-dessous.

raywenderlich.com Weekly

La newsletter de raywenderlich.com est le moyen le plus simple de rester à jour sur tout ce que vous devez savoir en tant que développeur mobile.

Recevez un condensé hebdomadaire de nos tutoriels et de nos cours, et recevez en prime un cours approfondi gratuit par courriel !

Note moyenne

4.8/5

Ajouter une note pour ce contenu

Se connecter pour ajouter une note

10 notes

.

Leave a Reply