Aide En Informatique
Latest Posts:

Gestion des états (State Management ) en Flutter avec Bloc/Cubit et les Repository Pattern
Gestion des états (State Management ) en Flutter avec Bloc/Cubit et les Repository Pattern

Il faut au prealable avoir dejà lu les posts suivant (ces liens demandent d'etre abonné du blog si vous ne l'etes pas encore faite le c'est un seul click vous pouvez utilisez votre compte facebook ou google pour le faire):

1=> Documentation tecnique backen/Backoffice/API REST c'est ici

2 => Documentation technique Flutter + Reactjs c'est ici

3=> Fonctionalité QuizCodeur c'est ici 

4=> Fonctionalité à ajouter, integrer, developper => ici

5=> Commment fonctionne réellement Flutter => c'est par ici 

A Quoi sert un State Manager ou mieux un Gestionnaire des etats dans une application?

Dans mon post recent, j'ai parlé de l'utilité d'un gestionnaire des états dans flutter, mais les state manager ne sont pas que utiles à flutter mais à toutes les applications d'ailleur le modele de flutter pour la gestion des états a été pris dans le framework reactjs de facebook. Toute application qu'on le veule ou non à un moment donné, doit gerer les états de l'application, la programmation en essence est la manipulation des variables et des structures de données pour resoudre à travers les algorithmes les besoins de l'utilisateur, donc une application qui ne manipule pas les données n'en est pas une et les données change dans le temps durant le cycle de vie de l'application, rarement les données sont statiques car chaque interaction de l'utilisateur à travers l'interface graphyque force l'application à avoir des états differents qui correspondent à l'etat des variables qui varient dans le temps en fonction de l'interaction avec l'utilisateur. Reguardez l'image suivant qui est le projet de defaut de flutter (Counter app), la app est simple et fait une seule chose, quand l'utilisateur fait un click sur le bouton +. il y a incrementation d'un nombre au centre de la app dans un champ de Text, il y a une variable- disons X=0 au depart de la app qui doit contenir la valeur de l'incrementation du click de l'utilisateur et chaque fois que l'utilisateur fait un click sur lebounton + on incremente cette valeur donc X=X+1 et cela est visible dans le texte box, passé de X=0 + X=X+1 est un changement d'état et chaque fois qu'il y a changement d'etat, flutter doit redessiner à zero toute l'arbre du widget en question (à savoir le widget et tous ses fils), en fait flutter étant fait d'un arbre infinie de widget  les uns les autres et chacun ayant des etats(variables) associé à lui, on arrive facilement à se retrouver avec une multitude de widget dans la gerachie de la app qui doivent se passer les etats, par exemple si la app recupere au debut du lancement de l'application les produits de l'api rest en backend, il serait utile de le mettre globalement a disposition de tous les widgets qui en auront besoin et eviter de le passer de widget en widget, voilà pourquoi il convient dans une application complexe d'utiliser des gestionnaires des etats qui permettent de centraliser les etats de manière à les mettre disponible à tous les widgets qui en ont besoin.

Flutter a nativement : setState() ,InheritedWidget, InheritedModel pour la gestion des états mais dans une application complexe comme notre application QuizCodeur, cela devient extrement difficile de les utiliser(immaginez les widgets qui doivent se passer les données de gauches à droite comme dans l'image ci dessous), raison pour laquelle dans les solutions d'entreprise ont fait recourt à certaines bibliothèques externes pour la Gestion des etats, dans Flutter il y en a une multitude mis sur pied par la communauté des developpeur flutter donc Bloc/Cubit qui est l'objet de ce post et utilisé dans QuizCodeur et GetX que j'adores personnelement et donc j'en reparlerai dans un autre. post.

Qu'est ce que le Repository Pattern et c'est quoi son utilité dans un projet?

Quand on projecte une application, il faut chercher dans la majorité des cas à y introduire des abstractions, un logiciel bien fait est plein de beaucoup d'abstraction(boite noire), les abstraction permet d'isoler des fonctionalités qu'on pourra utiliser dans d'autres part de l'application comme une boite noire sans se soucier effectivement de ce qui est fait dans cette boite noire, les framework que nous utilisons par exemple nous font beaucoup d'abstraction qu'on utilise sans meme savoir ce qui se passe internement dans le framework il suffit juste de respecter les conventions, nous utilisons regulièrement plein de bibliothèque pour faire telle ou telle autre chose dans nos projets sans meme aller lire le code source de ses bibliothèques pour savoir exactement comment est  codé telle ou telles autres fonctionalités, l'essence meme de la POO(Programmation à objet) c'est d'introduire les abstractions à travers les classes et tous les principes de la OOP, le Repository Pattern est donc une architecture ou on essaye de creer une abstration pour isoler les données (du moins la source ou la provenance) qu'on doit manipuler dans notre application, de manière que toute interaction avec notre app qui necessite de manipuler les données puissent faire recourt au repository(depotoire) de données pour le faire sans jamais savoir sa provenance par exemple si les données proviennent d'une base de données locale à la app ou bien d'un api rest en backend etc.. l'image associé à ce post vous donne une idée exacte de ce que je viens de dire. Dans Flutter, le triplet Bloc/Cubit-Repository pattern permet de faire un bon menage et de structurer tres tres bien son code surtout quand l'application devient complexe, le repository deviendra le seul depotoire qu'on interrogera chaque fois qu'on a besoin des données, Bloc/Cubit nous sera utile pour la gestion des états, chaque fois que l'utilisateur interagit avec nos widget sur l'interface graphyque, cela emet des evenements de manière reactive sur Bloc et à travers BlocProvider (un widget speciale Block) on peut recuperer l'etat de ce widget dans n'importe quel gerarchie de l'arbre sans ne plus se passer des données de manière non ordonner de gauche à droite.

Nous allons faire une demonstration simple avec code source à l'appui de l'utilsation de tout ce qui a été decrit ci haut pour comprendre le fonctionnement et ainsi, pour ceux qui experimente un peu dans le projet QuizCodeur, ils se retrouveront immediatement (pour ceux qui veulent participer à l'evolution de ce projet, il suffit de me donner votre compre github et vous serez associé au projet, la strategie est la meme, training on the job ou learning by doing). Nous allons consomer cette API REST (https://jsonplaceholder.typicode.com/posts) qui represente les POST d'un blog par exemple en creant une petite application flutter qui met en évidence Bloc/Cubit et les repository pattern.Vous devez avoir android studio pour suivre cette demo si vous ne l'avez pas faite le en allant ici

Lancez Android studio et creez un nouveau projet Flutter appellé "BlocCubitRepository"

Nous allons ajouter les bibliothèques(package) que nous avons besoin pour cette demo à savoir la bibliothèque pour faire les requetes HTTP et celle de Bloc, ouvrez le fichier "pubspec.yaml" qui est celui ou on indique à flutter les bibliothèques et les dependences de notre projets et ajoutez ces bibliothèques comme en image (vous devez etre en aborescence Project pour voir ce fichier)

fait en suite un click sur "Pub get" (4) pour mettre à jour ses dependences.

Question de mieux organiser notre code, Dans le repertoire lib ou on doit mettre notre code dart de la app, creez trois sous repertoires comme en images "repository avec un sous repertoire model" et "cubit" et "ui" avec un autre sous repertoire "screen":

Dans le sous repertoire model de repository, creez un fichier model.dart qui va representé la structure de données des POST  avec le code suivant:

créez un fichier "network_service.dart"  dans le repertoire "repository" avec le code suivant 

 en 1 nous importons la bibliothèque http que nous avons mis dans pubspec.yaml qui nous permet de faire des requetes http sur le lient en 2,  et nous l'utilisons en 3 pour recuperer les poste que l'on decode en json.

Creez toujours dans repository un autre fichier dart appellè "repository.dart" avec le code suivant:

Le repository est notre abstration pour obtenir les données des posts de l'API REST, c'est l'unique depotoire à qui il faut faire reference si on veut obtenir les pots et on isole ainsi cette fonctionalité de notre application dans ce fichier qui contient juste cette methode

Dans le repertoire cubit, creez le fichier "post_state.dart" qui va contenir les etats des posts qui constituent en fait le model de notre app et inserrez le code suivant:

les etats possibles que nous pouvons avoir sont : etat initiale ou on va faire la requete pour avoir les post et l'utilisateur ne voit encore rien à l'ecran, l'etat successif ou on a obtenu les données de l'API REST et l'utlisateur peut donc les voir à l'ecran et enfin l'etat ou il y a erreur

creez dans le meme repertoire un fichier "post_cubit.dart" avec le code suivant:

dans ce code on a toute la magie de Bloc/cubit, on doit heriter d'une classe cubit et passé notre état definit precedement, on passe notre repository au constructeur de la classe ce qui va nous servir ensuite à interroger l'API REST et recuperer les données, en utilisant les repository, on a eviter ainsi de cabler la requete HTTP directement dans la logique de cubit et ainsi notre code est plus ergonomique et plus lisible

Cubit étant l'objet par qui nous devons passer pour gerer les etats de notre app on a ce qui suit dans l'image: nous creons une methode fetchPost pour recuper les Posts, au depart on emt notre etat initiale 2, ensuite en 3 on utilise notre boite noire(abstraction) de la repository pour recuper les POSTs, s'il n'y a pas d'erreur on emet l'etat loaded avec les posts reçu du backend et en cas d'erreur on emet les erreur avec le message d'erreur et avec ces informations on va mettre à jour l'interface utilisateur.

Dans le repertoire UI/Screen creons un fichier "post_screen.dart" qui va contenir l'interface utilisateur avec le code suivant:

Au demarrage de la app, flutter appelle la methode initialState dans le cycle de vie de la app et nous en profitons pour faire une requete à l'API REST à travers cubit qui est devenu le gestionnaire des etats de notre app à travers la ligne de code suivante

Tout se joue ensuite dans la methode Build pour dessiner nos widget à l'ecran, nous devons embriquer nos widget dans un Blocbuilder en 1 e lui passant la classe Cubit et l'etat à gerer, puis en 2 on verifie dans quel etat on est si on est à l'etat initiale, on faire voir à l'utilisateur un icone de chargement, quand l'etat change et qu'on a reçu des posts en 3, on fait voir les POsts dans une listview en cas d'erreur on passe à l'etape 4 ou on change l'etat et on fait voir l'erreur.

Modifier enfin votre fichier principale main.dart pour qu'il contienne le code suivant:

si vous lancez la app vous obtenez l'image suivante qui charge les Pots de l'API REST, vous remarquerez qu'au debut il y a une image de telechargement qui respecte la première etape puis vient ensuite l'etat loaded ou on a les post et hop on y est:

Le code source de ce projet est disponible sur mon account github ici


Author: admin
05.09.2022, 14:35
Category: Coding
Comments: 0
Views: 736
-

Share

Comments (0)
There are no comments yet.

Leave A Comment
processing...