En tant que développeur, l'un des défis constants auxquels nous sommes confrontés est la gestion efficace des données au sein de nos applications. Que ce soit pour stocker des fichiers locaux, utiliser une base de données SQL ou noSQL pour des opérations plus complexes, ou simplement stocker des paires clé-valeur sur le disque, la persistance des données est cruciale.
Dans cet article, je vous présenterai les différentes manières d’y parvenir et nous allons créer un cas concret pour explorer la profondeur d’un aspect essentiel de la persistance des données dans Flutter, en nous inspirant de l’une des plus belles applications poussée par Google : Wonderous de la team Gskinner.
Pour ceci, nous allons créer ensemble un exemple d’onBoarding dans une application. L'onBoarding dans une application désigne le processus par lequel les utilisateurs sont guidés à travers les fonctionnalités clés lors de leur première utilisation. Il vise à familiariser rapidement les nouveaux utilisateurs avec l'interface, les caractéristiques et les avantages de l'application, favorisant ainsi une expérience utilisateur positive.
Présentation des possibilités de persistance de données
Lecture et écriture de fichiers dans Flutter
L'un des moyens les plus simples, mais essentiels pour stocker des données dans une application Flutter est la manipulation de fichiers.
Pour enregistrer des fichiers sur disque dans des applications Flutter, combinez le pluginpath_provider avec la bibliothèquedart:io. Voici l’exemple de la lecture et l’écriture d’un Int dans un fichier local.
Stockage de données clé-valeur sur le disque
Pour des besoins plus simples, où une base de données complète pourrait être excessive, le stockage de données clé-valeur sur le disque est une option rapide et efficace.
En utilisant le packageshared_preferences, vous pouvez stocker facilement des paires clé-valeur de manière persistante. Cela s'avère particulièrement utile pour les préférences utilisateur, les configurations d'application, ou toute autre donnée simple dont la persistance est nécessaire.
Bien que le stockage clé-valeur fourni par shared_preferences soit facile et pratique à utiliser, il présente des limites :
Seuls les types primitifs peuvent être utilisés : int, double, bool, String et List<String>.
Il n'est pas conçu pour stocker de grandes quantités de données.
Il n'y a aucune garantie que les données seront conservées après le redémarrage de l'application.
Lorsque vos besoins en matière de persistance de données deviennent plus complexes, la transition vers une base de données SQLite peut être la solution idéale.
Le package sqflite couvre la création de bases de données, l'insertion, la mise à jour, et la récupération de données.
Création d’un onBoarding grâce à la persistance locale
Présentation du contenu de base
Nous allons tirer parti du packageshared_preferences pour faire comprendre à l’application que l’utilisateur est déjà passé par le processus d’onboarding, et qu’il n’a pas besoin de l’afficher. Nous possédons déjà la HomePage et la OnBoardingPage qui s'occupent respectivement de l’accueil de l’utilisateur et de l’onboarding.
Nous avons un main.dart qui est présenté comme tel.
Création du router
Nous allons utiliser la librairiego_router poussée par Google pour la navigation intra-application. Nous créons un fichier router.dart qui permettra de centraliser et d’avoir une vision claire sur la navigation dans notre application.
Notre MainApp() dans main.dart utilise maintenant MaterialApp.router pour faire fonctionner ce nouveau routeur.
Nous pouvons donc ajouter au clic du bouton Done la navigation vers la HomePage.
Création de la logique
Nous créons AppLogic qui servira de gestionnaire de tous les services de l’application et s’occupera de les initialiser. Puis nous créons le service SettingsLogic qui s’occupera de toutes les préférences utilisateurs, dont s'il a complété le onboarding ou non.
Nous allons utiliser le packageget_it qui permet d'accéder à l'implémentation concrète à partir de n'importe quel endroit de votre application. Cela répond au paterne d’injection de dépendances et offre une belle modularité dans la gestion des services et des classes de logiques.
Notre main.dart ressemble maintenant à ceci.
Nous avons un début d’architecture qui nous permet d’accéder à la navigation et aux paramètres de l’application n’importe où dans le code. Nous pouvons donc compléter notre fonction _validateOnBoarding dans la OnBoardingPage pour qu’elle notifie le service que l’onboarding s’est bien terminé.
Sauf que l’information n’est pas gardée au redémarrage de l’application, il faut trouver un moyen de le faire facilement.
Faire persister l’information du service au démarrage
Passons au plus important : garder l’information entre chaque démarrage de l’application. Nous aurons deux armes importantes. Une première classe JsonPrefsFile qui permettra d’utiliser l’instance du shared_preferences et transformer n’importe quel objet JSON en String afin de pouvoir le stocker dans une référence clé-valeur sur le disque. Un second mixinSaveLoadMixin qui sera utilisé pour la sérialisation des informations des services en JSON et fera appel au JsonPrefsFile afin de stocker l’information.
JsonPrefsFile possède deux méthodes load() et save() qui permettent respectivement de manipuler le JSON et de l’enregistrer ou de le récupérer. SaveLoadMixin sera utile sur nos services, car il permettra d’avoir des méthodes pour serialiser l’information (toJson, copyFromJson) et deux méthodes pour enregistrer et récupérer l’information (save, load).
Notre SettingsLogic va maintenant pouvoir utiliser ces méthodes. On transforme aussi hasCompletedOnboarding avec des getter et des setters, qui permettront que lorsque hasCompletedOnboarding change, on appele le save() hérité qui enregistre la donnée.
L’information est maintenant enregistrée à chaque modification du service, il nous reste simplement à ajouter dans notre boostrap() du AppLogic() qu’il faut initialiser le settingsLogic en appelant load()qui va récupérer l’information stockée.
Bonus : garder le splashScreen pendant le bootstrap de l’application
Le packageflutter_native_splash nous permet de personnaliser l'écran d'accueil blanc par défaut de Flutter avec une couleur d'arrière-plan et une image d'accueil. Il nous permet aussi de retenir cet écran le temps qu’on souhaite, dans notre cas, le temps que l’AppLogic fasse son boostrap. Cela donne une dernière modification pour notre `main` .
Conclusion
Nous avons vu comment conserver l’information du onboarding et comment créer une logique de services pour gérer les préférences d’une application avec l’utilisation des packages get_it, go_router, shared_preferences, flutter_native_splash.
Les sources du projet sont présentes sur ce repository. J'espère que ces informations vous seront utiles dans vos projets de développement Flutter, n’hésitez pas à partager cet article.
N'oubliez pas que le monde du code est un terrain de jeu infini, et chaque ligne que vous écrivez peut être une aventure en soi. Happy coding!