• 8 hours
  • Easy

Free online content available in this course.

course.header.alt.is_certifying

Got it!

Last updated on 9/4/23

Gérez les données du quiz

Créez le modèle de données

Avant de débuter la conception de la couche Données de l’architecture de notre application, jetons un coup d'œil à la maquette ci-dessous, afin de comprendre comment doit fonctionner le quiz de notre application.

L'illustration reprend les situations décrites en dessous dans le texte.
  • En cliquant sur une réponse (1), l’interface se met à jour pour indiquer à l’utilisateur si la réponse est bonne ou non, et le bouton "Suivant" apparaît (2).

  • En cliquant sur le bouton “Next” (2), l’interface se met à jour pour afficher une nouvelle question. À nouveau l’utilisateur clique sur une réponse (3), etc.

  • Lorsque l’utilisateur a répondu à la dernière question, le bouton “Finish” apparaît (4).

  • En cliquant sur le bouton “Finish”, une fenêtre de dialogue apparaît pour indiquer à l’utilisateur son score final (5). En cliquant sur “Quit”, le fragment QuizFragment  est remplacé par le fragment WelcomeFragment  .

Pour concevoir cette fonctionnalité, nous devons modéliser l’objet représentant une question du quiz. Cet objet se caractérise par : 

  • la question représentée par une chaîne de caractères ;

  • les propositions représentées par une liste de chaînes de caractères ;

  • la bonne réponse, représentée par un entier correspondant à l’index de proposition correcte dans la liste précédente.

Pour modéliser cet objet, nous allons créer une classe Java nommée Question  .

Pour créer un nouveau package data  dans Android Studio, faites un clic droit sur le package principal de votre projet au sein de l’arborescence de fichier, puis allez dans le menu New et sélectionnez Package.

Capture d’écran d'Android Studio montrant l’accès au menu permettant de créer un nouveau package en faisant un clic droit dans l’arborescence de fichiers.
Créez un nouveau package avec Android Studio

Une fenêtre apparaît alors, vous permettant de saisir le nom du nouveau package. Complétez le chemin actuel en ajoutant à la fin “data”.

Capture d’écran d'Android Studio montrant la fenêtre permettant de saisir le nom du nouveau package.
Créez un nouveau package data avec Android Studio

Dans ce package, nous allons créer une classe Question  . Pour cela, dans l’arborescence de fichier, faites un clic droit sur le package data  , puis allez dans le menu New et cliquez sur Java Class. Saisissez “Question” dans la fenêtre qui apparaît puis tapez sur Entrée .

Capture d’écran d'Android Studio montrant la fenêtre permettant de créer une nouvelle classe Question.
Créez une classe Question

L'instance de cette classe contiendra une question, avec les quatre réponses associées et la bonne réponse correspondante. De ce fait, elle va contenir les trois attributs privés suivants :

private final String question;
private final List<String> choiceList;
private final int answerIndex;

Pensez bien à importer la classe Java List  comme ceci :  import  java.util.List;  .

Nous allons maintenant créer le constructeur et les fonctions getters et setters nécessaires pour cette classe. Pour rappel, pour une variable privée donnée, une fonction de type getter va permettre d’accéder à sa valeur, et une fonction de type setter de la modifier. Le constructeur va nous permettre de créer un objet de type Question  dans notre code.

Ne foncez pas tête baissée pour écrire à la main toutes ces fonctions. En effet, Android Studio vous permet de générer toutes ces fonctions automatiquement. Pour cela, positionnez le curseur de votre souris sur le nom de la classe Question  , puis faites un clic droit ou appuyez sur  ALT + Insert sur PC, ou + N sur Mac. Sélectionnez Getter and Setter. Dans la fenêtre qui s’affiche, sélectionnez les 3 variables et appuyez sur OK.

Capture d’écran d'Android Studio montrant la fenêtre permettant de sélectionner les variables de la classe Question pour laquelle générer automatiquement les getters et setters.
Générez les getters et setters des 3 variables privées de la classe Question

Renouvelez l’opération en sélectionnant cette fois-ci Constructor dans la liste, en prenant soin de bien sélectionner les trois variables de la classe Question  en tant que paramètres du constructeur.

Vous devriez à la fin obtenir le code ci-dessous pour la classe Question  :

public class Question {

    private final String question;
    private final List<String> choiceList;
    private final Integer answerIndex;

        public Question(String question, List<String> choiceList, int answerIndex) {
        this.question = question;
        this.choiceList = choiceList;
        this.answerIndex = answerIndex;
    }

    public String getQuestion() {
        return question;
    }

    public List<String> getChoiceList() {
        return choiceList;
    }

    public Integer getAnswerIndex() {
        return answerIndex;
    }
}

Chouette, nous avons maintenant une classe Java qui va nous permettre de représenter l’objet principal de notre quiz. Mais où sont les données ?

C’est justement l’objectif de la prochaine section !

Récupérez les données

Les données d’une application peuvent provenir de différentes sources :

  • un fichier ; 

  • une base de données locale (par exemple via la bibliothèque Room) ;

  • une API externe (par exemple via la bibliothèque Retrofit).

Pour notre application, bien que dans la réalité, nous aurions certainement fait appel à une API pour récupérer une liste de questions aléatoires, pour des raisons de simplicité, nous allons créer une banque de questions “en dur” dans une classe Java.

Pour ce faire, dans le package data  , nous allons créer une classe Java nommée QuestionBank  . Elle va exposer une fonction getQuestions()  qui retournera une liste de questions prédéfinie. Ci-dessous la classe que j'ai développée. Vous verrez, mes questions ne sont pas très fun, alors n’hésitez pas à inventer vos propres questions.

public class QuestionBank {
    public List<Question> getQuestions() {
       return Arrays.asList(
                new Question(
                        "Who is the creator of Android?",
                        Arrays.asList(
                                "Andy Rubin",
                                "Steve Wozniak",
                                "Jake Wharton",
                                "Paul Smith"
                        ),
                        0
                ),
                new Question(
                        "When did the first man land on the moon?",
                        Arrays.asList(
                                "1958",
                                "1962",
                                "1967",
                                "1969"
                        ),
                        3
                ),
                new Question(
                        "What is the house number of The Simpsons?",
                        Arrays.asList(
                                "42",
                                "101",
                                "666",
                                "742"
                        ),
                        3
                ),
                new Question(
                        "Who painteddid the Mona Lisa paint?",
                        Arrays.asList(
                                "Michelangelo",
                                "Leonardo Da Vinci",
                                "Raphael",
                                "Caravaggio"
                        ),
                        1
                ),
                new Question(
                        "What is the country top-level domain of Belgium?",
                        Arrays.asList(
                                ".bg",
                                ".bm",
                                ".bl",
                                ".be"
                        ),
                        3
                )
        );
   }
    private static QuestionBank instance;
    public static QuestionBank getInstance() {
        if (instance == null) {
         instance = new QuestionBank();
        }
        return instance;
    }
}

Si nous reprenons le schéma précédent, nous avons maintenant la couche Données qui contient nos fameuses questions grâce à la classe  QuestionBank  .

Schéma illustrant les deux couches “Vue” et “Données” par deux blocs, avec un bloc intermédiaire intitulé “ViewModel”. Le bloc Données contient maintenant la classe QuestionBank représentée par un autre bloc.
Illustration de la couche Données contenant maintenant QuestionBank

OK on avance, maintenant nous avons des données dans notre couche Données. Mais comment fait-on pour y accéder depuis le ViewModel ?

Pour exposer les données dont l’application a besoin, nous allons utiliser le pattern Repository (oui, je sais, encore un pattern…). Voyons à quoi il va servir.

Le pattern Repository

Ce pattern consiste à utiliser une classe intermédiaire pour servir de médiateur entre le ViewModel et les différentes sources de données.

Mais en quoi avons-nous besoin de médiation ? Les données sont là, ne peut-on pas les envoyer telles quelles en utilisant QuestionBank directement depuis le ViewModel ?

On pourrait effectivement utiliser QuestionBank  directement depuis le ViewModel. Mais ici, on va apprendre à faire les choses comme dans la vraie vie de développeur ou développeuse en entreprise.

Pour comprendre la nécessité d’un médiateur tel que le Repository, revenons à notre couche Données. Bien que dans notre cas les données proviennent d’une source unique via le fichier QuestionBank  , il est courant dans une application de devoir combiner plusieurs sources de données. Typiquement, une base de données locale et une API externe. 

Pour l’application SuperQuiz, nous pourrions par exemple imaginer dans le futur de récupérer des questions sur internet depuis un serveur, et de les stocker dans une base de données locale sur le téléphone. Cela faciliterait par exemple l’utilisation de l’application hors connexion. C’est l’une des raisons qui justifie l’usage du pattern Repository.

Les données sont récupérées du repository pour être affichées dans l'application.
Le pattern repository

Un Repository permet donc de :

  • centraliser l’accès aux données ;

  • gérer à un endroit unique la logique permettant de définir quelle source de données utiliser.

Si nous reprenons notre schéma, cela donne ça :

Le bloc Données contient toujours la classe QuestionBank et maintenant la classe QuestionRepository, qui est reliée par une flèche à double sens au ViewModel, indiquant que les deux blocs communiquent entre eux.
Illustration de la couche Données contenant maintenant la classe QuestionRepository

À vous de jouer !

Maintenant, à vous de créer le Repository pour nos questions !

Dans le package data  ,  créez une classe Java intitulée QuestionRepository  .

Celle-ci prend en paramètre la source de données unique QuestionBank  . N’oubliez pas de déclarer le constructeur de cette classe.

Enfin, faites en sorte que cette classe expose une fonction getQuestions()  qui retourne la liste des questions issues de la banque de questions.

Essayez seul(e), avant de regarder la solution ci-dessous.

public class QuestionRepository {
    private final QuestionBank questionBank;

    public QuestionRepository(QuestionBank questionBank) {
        this.questionBank = questionBank;
    }

    public List<Question> getQuestions() {
        return questionBank.getQuestions();
    }
}

Récapitulons en vidéo

Retrouvez ces différentes étapes dans la vidéo ci-dessous :

En résumé

  • Pour concevoir la couche Données d’une fonctionnalité, il faut identifier les modèles de données spécifiques à l’application, et créer un objet Java pour chaque modèle.

  • Il est d’usage de positionner tous les fichiers relatifs à la couche Données au même endroit, par exemple dans un package data  .

  • Les données d’une application peuvent provenir de différentes sources : un fichier, une base de données locale, une API externe, etc.

  • Une fois la provenance des données déterminée, la logique permettant d’arbitrer quelles données utiliser se trouve dans une classe de type Repository. 

  • Le Repository est le seul à pouvoir accéder aux données.

  • Il convient de créer un Repository par type de donnée dont l’application a besoin.

Notre couche Données est maintenant développée, et la fonction getQuestions()  du Repository QuizRepository  est prête à être appelée depuis le ViewModel associé à l’écran de quiz. Nous allons maintenant coder la logique métier spécifique à notre fonctionnalité de quiz dans le ViewModel associé.

Example of certificate of achievement
Example of certificate of achievement