Flutter
...
Data Objects
Types de données Parse dans Flutter : Guide Technique
19 min
ce guide présente les types de données parse dans flutter, en utilisant des exemples du main dart fichier le stockage de données parse tourne autour de parseobject, qui contient des paires clé valeur de données compatibles json, ce qui le rend sans schéma cela signifie que vous pouvez stocker n'importe quelles données sans définir un schéma à l'avance vous pouvez définir les paires clé valeur que vous souhaitez, et notre backend les stockera par exemple, disons que vous suivez les meilleurs scores pour un jeu un seul objet parse pourrait contenir nous vous suggérons de nameyourclasseslikethis et nameyourkeyslikethis pour améliorer la lisibilité et la maintenabilité du code comprendre notre application pour mieux comprendre back4app, explorons des exemples de code des opérations parse dans une application flutter avec les principaux types de données pris en charge ce guide n'expliquera aucun code d'application flutter car l'objectif principal est d'utiliser parse avec flutter prérequis pour compléter ce tutoriel, vous aurez besoin de android studio https //developer android com/studio ou vs code installé (avec plugins dart et flutter) une application créée sur back4app remarque suivez le tutoriel de la nouvelle application parse pour apprendre à créer une application parse sur back4app une application flutter connectée à back4app remarque suivez le installer le sdk parse sur le projet flutter pour créer un projet flutter connecté à back4app un appareil (ou un appareil virtuel) exécutant android ou ios 1 travailler avec des objets parse chaque parseobject a un nom de classe (par exemple, gamepoint) utilisé pour distinguer différents types de données voici comment vous pouvez créer et enregistrer un nouvel objet parse avec des types de données string , int , & boolean final gamepoint = parseobject('gamepoint') set('score', 1337) set('playername', 'sean plott') set('cheatmode', false); await gamepoint save(); pour interroger le nouvel objet parse et récupérer les types de données final querybuilder\<parseobject> querygamepoints = querybuilder\<parseobject>(parseobject('gamepoint')); final parseresponse response = await querygamepoints query(); if (response success && response results != null) { for (var gamepoint in response results!) { final score = gamepoint get\<int>('score'); final playername = gamepoint get\<string>('playername'); final cheatmode = gamepoint get\<bool>('cheatmode'); } 2 compteurs vous pouvez incrémenter ou décrémenter un champ entier dans un parseobject en utilisant la set() méthode cependant, cela n'est pas efficace et peut entraîner des problèmes si plusieurs clients essaient de mettre à jour le même compteur parse fournit deux méthodes qui incrémentent et décrémentent automatiquement tout champ numérique pour stocker des données de type compteur setincrement() setdecrement() une mise à jour pour incrémenter un compteur int sera écrite comme suit final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setincrement('intfield', 1); await gamepoint save(); pour décrémenter final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setdecrement('intfield', 1); await gamepoint save(); utiliser setincrement() et setdecrement() avec l'appel save() vous permet de mettre à jour une valeur dans le cadre d'une opération de sauvegarde plus large où vous pourriez modifier plusieurs champs c'est mieux pour éviter des requêtes réseau supplémentaires 3 listes parse fournit des méthodes pour travailler avec des données de liste, y compris setadd , setaddunique , setremove , et leurs versions all respectives liste \["a","b","c"] 3 1 setadd final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setadd('liststringfield', 'd'); await gamepoint save(); résultat \["a","b","c","d"] 3 2 setaddall final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setaddall('liststringfield', \['e','f']); await gamepoint save(); final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setaddall('liststringfield', \['e','f']); await gamepoint save(); résultat \["a","b","c","d","e","f"] setaddall n'ajoute pas d'éléments en double si la liste les contient déjà 3 3 setaddunique final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setaddunique('liststringfield', \['a', 'e', 'g']); await gamepoint save(); résultat \["a","b","c","d","e","f","g"] 3 4 setremove final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setremove('liststringfield', 'd'); await gamepoint save(); résultat \["a","b","c","e","f","g"] 4 supprimer un champ de parseobject vous pouvez supprimer un seul champ d'un objet en utilisant l'opération unset final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' unset("liststringfield"); 5 fichiers parsefile vous permet de stocker et de récupérer des fichiers d'application dans le cloud voici un exemple de base pour télécharger un fichier image local sur back4app // create parsefile object final parsefile = parsefile(file(image path)); final response = await parsefile save(); if (response success) { print('file uploaded successfully ${parsefile url}'); // save this file in an object final gamepoint = parseobject('gamepoint') set('title', 'post with an image') set('imagefile', parsefile); // saving the file as a field final postresponse = await gamepoint save(); } ce extrait de code montre comment récupérer le fichier image final query = querybuilder\<parseobject>(parseobject('gamepoint')); final response = await query query(); if (response success && response results != null) { for (var gamepoint in response results!) { parsefilebase? varfile = gamepoint get\<parsefilebase>('file'); if (varfile != null) { final fileurl = varfile url; print('game title image url $fileurl'); } else { print('no file found for this object '); } } } à partir de parse server 5 2 3 il y a des changements qui pourraient causer des erreurs lors d'une tentative de téléchargement de fichiers suivez ce guide https //www back4app com/docs/platform/parse server version#o cil pour résoudre tout problème de téléchargement que vous pourriez rencontrer un guide ultérieur discutera davantage et montrera des modèles sur comment sauvegarder et afficher des fichiers avec parse https //www back4app com/docs/flutter/parse sdk/flutter save file 6 geopoint parse vous permet d'associer des coordonnées de latitude et de longitude du monde réel à un objet avec son type de données geopoint ajouter un parsegeopoint à un parseobject permettra aux requêtes de prendre en compte la proximité d'un objet par rapport à un point de référence exemple // request permission here and get the current location the `position` object // create geopoint object final geopoint = parsegeopoint(latitude position latitude, longitude position longitude); // create an object with the geopoint final gamepoint = parseobject('gamepoint') set('name', 'current location') set('location', geopoint); // save the geopoint in a field final response = await gamepoint save(); vous pouvez trouver un exemple autonome de sauvegarde de la localisation geopoint dans ce main dart https //github com/templates back4app/flutter datatypes/blob/18c4c372eb49c1cd950eeaac355564134a5e70c4/lib/src/main dart fichier exemple d'application complète cet exemple démontre comment créer, supprimer et mettre à jour un gamepoint objet parse gérer divers types de données, y compris des chaînes, des doubles, des booléens, des fichiers, des géopoints, des listes et des dates sur ios, vous devrez accorder à votre simulateur les autorisations d'accès nécessaires ios fournit un guide pour les développeurs sur les ressources protégées les applications d'exemple dans ce guide nécessiteront les clés de permission location https //developer apple com/documentation/bundleresources/information property list/nslocationwheninuseusagedescription et photos https //developer apple com/documentation/bundleresources/information property list/nsphotolibraryaddusagedescription trouvées dans ce guide pour fonctionner ajoutez les clés au fichier info plist situé à /ios/runner/info plist vous pouvez ignorer l'étape ci dessus si vous exécutez votre application flutter sur le web import 'dart\ async'; import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk flutter dart'; import 'package\ image picker/image picker dart'; import 'package\ flutter/foundation dart'; import 'dart\ io'; void main() async { widgetsflutterbinding ensureinitialized(); const keyparseapplicationid = 'your application id'; const keyparseclientkey = 'your client key'; const keyparseserverurl = 'https //parseapi back4app com'; await parse() initialize( keyparseapplicationid, keyparseserverurl, clientkey keyparseclientkey, autosendsessionid true, debug true, ); runapp(const myapp()); } class myapp extends statelesswidget { const myapp({super key}); @override widget build(buildcontext context) { return materialapp( title 'datatypes', theme themedata( primaryswatch colors blue, ), home const myhomepage(), ); } } class myhomepage extends statefulwidget { const myhomepage({super key}); @override myhomepagestate createstate() => myhomepagestate(); } class myhomepagestate extends state\<myhomepage> { final texteditingcontroller stringcontroller = texteditingcontroller(); final texteditingcontroller doublecontroller = texteditingcontroller(); final texteditingcontroller liststringcontroller = texteditingcontroller(); final texteditingcontroller listintcontroller = texteditingcontroller(); final texteditingcontroller pointercontroller = texteditingcontroller(); final texteditingcontroller objectidcontroller = texteditingcontroller(); final texteditingcontroller uniquevaluecontroller = texteditingcontroller(); final texteditingcontroller removevaluecontroller = texteditingcontroller(); bool boolvalue = false; datetime selecteddate = datetime now(); final string responsemessage = ''; xfile? pickedfile; bool isloading = false; @override widget build(buildcontext context) { return scaffold( appbar appbar( title const text('datatypes'), ), body padding( padding const edgeinsets all(16 0), child singlechildscrollview( child column( crossaxisalignment crossaxisalignment start, children \<widget>\[ buildtextfield('string field', stringcontroller), const sizedbox(height 20), buildtextfield('double field', doublecontroller, isnumeric true), const sizedbox(height 20), buildswitch('bool field', boolvalue, (value) { setstate(() { boolvalue = value; }); }), const sizedbox(height 20), textbutton( onpressed () => selectdate(context), child text( 'select date ${ selecteddate tolocal()}' split(' ')\[0]), ), const sizedbox(height 20), buildtextfield( 'list string field (comma separated)', liststringcontroller), const sizedbox(height 20), buildtextfield( 'list int field (comma separated)', listintcontroller), const sizedbox(height 20), buildtextfield('pointer field (object id)', pointercontroller), const sizedbox(height 20), buildimagepicker(), const sizedbox(height 20), elevatedbutton( onpressed savedata, child const text('save'), ), const sizedbox(height 20), elevatedbutton( onpressed () async { await deletedata( objectidcontroller text); // await dummyfunction(); }, child const text('delete'), ), const sizedbox(height 20), buildtextfield( 'object id to delete or update', objectidcontroller), elevatedbutton( onpressed () async { await updatedata( objectidcontroller text); }, child const text('update'), ), const sizedbox(height 20), buildincrementdecrementbuttons(), const sizedbox(height 20), buildlistoperations(), const sizedbox(height 20), text( responsemessage), ], ), ), ), ); } widget buildtextfield(string label, texteditingcontroller controller, {bool isnumeric = false}) { return textfield( controller controller, keyboardtype isnumeric ? textinputtype number textinputtype text, decoration inputdecoration( border const outlineinputborder(), labeltext label, ), ); } widget buildswitch(string label, bool value, function(bool) onchanged) { return switchlisttile( title text(label), value value, onchanged onchanged, ); } widget buildimagepicker() { return gesturedetector( child pickedfile != null ? container( width 250, height 250, decoration boxdecoration(border border all(color colors blue)), child kisweb ? image network(pickedfile! path) image file(file(pickedfile! path)), ) container( width 250, height 250, decoration boxdecoration(border border all(color colors blue)), child const center( child text('click here to pick image from gamepoint')), ), ontap () async { final picker = imagepicker(); xfile? image = (await picker pickimage(source imagesource gallery)); if (image != null) { setstate(() { pickedfile = image; }); } }, ); } widget buildincrementdecrementbuttons() { return row( mainaxisalignment mainaxisalignment spacebetween, children \[ expanded( child elevatedbutton( onpressed () async { await incrementfield( objectidcontroller text); }, child const text('+ double'), ), ), const sizedbox(width 10), // adding some space between buttons expanded( child elevatedbutton( onpressed () async { await decrementfield( objectidcontroller text); }, child const text(' double'), ), ), ], ); } widget buildlistoperations() { return column( children \[ buildtextfield('unique value to add', uniquevaluecontroller), elevatedbutton( onpressed () async { await adduniquetolist( objectidcontroller text, uniquevaluecontroller text); }, child const text('add unique'), ), const sizedbox(height 20), buildtextfield('value to remove', removevaluecontroller), elevatedbutton( onpressed () async { await removefromlist( objectidcontroller text, removevaluecontroller text); }, child const text('remove'), ), ], ); } future\<void> savedata() async { //parse values string stringvalue = stringcontroller text; list\<string> liststringvalue = liststringcontroller text isnotempty ? liststringcontroller text split(',') // split by comma map((e) => e trim()) // remove any surrounding whitespace from each element tolist() \[]; list\<int> listtintvalue = listintcontroller text isnotempty ? listintcontroller text split(',') // split by comma map( (e) => int parse(e trim())) // convert each string to an integer tolist() \[]; double? doublevalue; if ( doublecontroller text isnotempty) { doublevalue = double parse( doublecontroller text); } bool boolvalue = boolvalue; datetime selecteddate = selecteddate; final gamepoint = parseobject('gamepoint') set('bool', boolvalue) set('date', selecteddate); if (stringvalue isnotempty) gamepoint set('string', stringvalue); if (doublevalue != null) gamepoint set('double', doublevalue); if (liststringvalue isnotempty) { gamepoint setaddall('liststring', liststringvalue); } if (listtintvalue isnotempty) gamepoint setaddall('listint', listtintvalue); if ( pointercontroller text isnotempty) { gamepoint set('pointer', parsepointer( pointercontroller text)); } if (pickedfile != null) { setstate(() { isloading = true; }); parsefilebase? parsefile; if (kisweb) { parsefile = parsewebfile(await pickedfile! readasbytes(), name 'file jpg'); } else { parsefile = parsefile(file(pickedfile! path)); } await parsefile save(); gamepoint set('file', parsefile); } var apiresponse = await gamepoint save(); if (apiresponse success && apiresponse results != null) { setstate(() { isloading = false; pickedfile = null; }); scaffoldmessenger of(context) removecurrentsnackbar() showsnackbar(const snackbar( content text( 'file saved successfully on back4app', style textstyle(color colors white), ), duration duration(seconds 3), backgroundcolor colors blue, )); } else { print("this is your request error ${apiresponse error}"); } } future\<void> updatedata(string objectid) async { final gamepoint = parseobject('gamepoint') objectid = objectid; // update fields with new values if ( stringcontroller text isnotempty) { gamepoint set('string', stringcontroller text); } if ( doublecontroller text isnotempty) { gamepoint set('double', double parse( doublecontroller text)); } gamepoint set('bool', boolvalue); gamepoint set('date', selecteddate); if ( liststringcontroller text isnotempty) { list\<string> liststringvalue = liststringcontroller text split(',') map((e) => e trim()) tolist(); gamepoint setaddall('liststring', liststringvalue); } if ( listintcontroller text isnotempty) { list\<int> listintvalue = listintcontroller text split(',') map((e) => int parse(e trim())) tolist(); gamepoint setaddunique('listint', listintvalue); } if ( pointercontroller text isnotempty) { gamepoint set('pointer', parsepointer( pointercontroller text)); } if (pickedfile != null) { parsefilebase? parsefile; if (kisweb) { parsefile = parsewebfile(await pickedfile! readasbytes(), name 'file jpg'); } else { parsefile = parsefile(file(pickedfile! path)); } await parsefile save(); gamepoint set('file', parsefile); } // save the updated object var response = await gamepoint save(); if (response success) { scaffoldmessenger of(context) showsnackbar( const snackbar(content text('data updated successfully!')), ); } else { scaffoldmessenger of(context) showsnackbar( snackbar( content text('error updating data ${response error! message}')), ); } } future\<void> incrementfield(string objectid) async { final gamepoint = parseobject('gamepoint') objectid = objectid setincrement('double', 1); await gamepoint save(); } future\<void> decrementfield(string objectid) async { final gamepoint = parseobject('gamepoint') objectid = objectid setdecrement('double', 1); await gamepoint save(); } future\<void> adduniquetolist(string objectid, string value) async { final gamepoint = parseobject('gamepoint') objectid = objectid setaddunique('liststring', value); await gamepoint save(); } future\<void> removefromlist(string objectid, string value) async { final gamepoint = parseobject('gamepoint') objectid = objectid setremove('liststring', value); await gamepoint save(); } future\<void> selectdate(buildcontext context) async { final datetime? picked = await showdatepicker( context context, initialdate selecteddate, firstdate datetime(2000), lastdate datetime(2101), ); if (picked != null && picked != selecteddate) { setstate(() { selecteddate = picked; }); } } future\<void> deletedata(string objectid) async { // delete data logic final parseobject = parseobject('gamepoint') objectid = objectid unset("liststring"); await parseobject save(); } // convert pointer field to a suitable format parseobject parsepointer(string objectid) { // there should be an existing game class with objects final pointer = parseobject('game') objectid = objectid; return pointer; } } ce code initialise le sdk parse dans flutter, configure l'application principale et affiche une simple page d'accueil avec un titre conclusion dans ce guide, vous avez appris sur les parseobjects et les différents types de données disponibles pour parse vous avez également appris comment gérer des opérations telles que l'enregistrement et la récupération des types de données vers et depuis votre backend back4app