Flutter
...
Data Objects
Parse-Datentypen in Flutter verstehen und implementieren
16 min
dieser leitfaden führt in die parse datentypen in flutter ein, anhand von beispielen aus der main dart datei die speicherung von parse daten dreht sich um parseobject, das schlüssel wert paare von json kompatiblen daten enthält, wodurch es schemalos ist das bedeutet, dass sie beliebige daten speichern können, ohne im voraus ein schema definieren zu müssen sie können beliebige schlüssel wert paare festlegen, und unser backend wird sie speichern zum beispiel, sagen wir, sie verfolgen die highscores für ein spiel ein einzelnes parse objekt könnte enthalten wir empfehlen ihnen, nameyourclasseslikethis und nameyourkeyslikethis zu verwenden, um die lesbarkeit und wartbarkeit des codes zu verbessern verstehen unserer app um back4app besser zu verstehen, lassen sie uns codebeispiele für parse operationen in einer flutter anwendung mit den wichtigsten unterstützten datentypen erkunden dieser leitfaden wird keinen flutter app code erklären, da der schwerpunkt auf der verwendung von parse mit flutter liegt voraussetzungen um dieses tutorial abzuschließen, benötigen sie android studio https //developer android com/studio oder vs code installiert (mit plugins dart und flutter) eine app erstellt auf back4app hinweis folgen sie dem neuen parse app tutorial , um zu lernen, wie man eine parse app auf back4app erstellt eine flutter app, die mit back4app verbunden ist hinweis folgen sie dem installieren sie das parse sdk im flutter projekt , um ein flutter projekt zu erstellen, das mit back4app verbunden ist ein gerät (oder virtuelles gerät), das android oder ios ausführt 1 arbeiten mit parse objekten jedes parseobject hat einen klassennamen (z b gamepoint), der verwendet wird, um verschiedene datentypen zu unterscheiden so können sie ein neues parse objekt mit datentypen erstellen und speichern string , int , & boolean final gamepoint = parseobject('gamepoint') set('score', 1337) set('playername', 'sean plott') set('cheatmode', false); await gamepoint save(); um das neue parse objekt abzufragen und die datentypen abzurufen 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 zähler sie können ein ganzzahliges feld in einem parseobject mit der set() methode erhöhen oder verringern dies ist jedoch nicht effektiv und kann zu problemen führen, wenn mehrere clients versuchen, denselben zähler zu aktualisieren parse bietet zwei methoden, die automatisch jedes zahlenfeld erhöhen und verringern, um zählerdaten zu speichern setincrement() setdecrement() ein update zur erhöhung eines zählers int wertes wird geschrieben als final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setincrement('intfield', 1); await gamepoint save(); um zu verringern final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setdecrement('intfield', 1); await gamepoint save(); die verwendung von setincrement() und setdecrement() mit dem save() aufruf ermöglicht es ihnen, einen wert als teil einer größeren speicheroperation zu aktualisieren, bei der sie möglicherweise mehrere felder ändern dies ist besser, um zusätzliche netzwerkrequests zu vermeiden 3 listen parse bietet methoden zur arbeit mit listendaten, einschließlich setadd , setaddunique , setremove , und deren jeweiligen all versionen liste \["a","b","c"] 3 1 setadd final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setadd('liststringfield', 'd'); await gamepoint save(); ergebnis \["a","b","c","d"] 3 2 setaddall final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setaddall('liststringfield', \['e','f']); await gamepoint save(); ergebnis \["a","b","c","d","e","f"] setaddall fügt keine doppelten elemente hinzu, wenn die liste sie bereits enthält 3 3 setaddunique final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setaddunique('liststringfield', \['a', 'e', 'g']); await gamepoint save(); ergebnis \["a","b","c","d","e","f","g"] 3 4 setremove final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' setremove('liststringfield', 'd'); await gamepoint save(); ergebnis \["a","b","c","e","f","g"] 4 feld aus parseobject entfernen sie können ein einzelnes feld aus einem objekt entfernen, indem sie die unset operation verwenden final gamepoint = parseobject('gamepoint') objectid = 'yourobjectid' unset("liststringfield"); 5 dateien parsefile ermöglicht es ihnen, anwendungsdateien in der cloud zu speichern und abzurufen unten finden sie ein einfaches beispiel zum hochladen einer lokalen bilddatei auf 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(); } dieser codeausschnitt zeigt, wie man die bilddatei abruft 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 '); } } } ab parse server 5 2 3 gibt es breaking changes, die fehler beim hochladen von dateien verursachen können folgen sie diesem leitfaden https //www back4app com/docs/platform/parse server version#o cil um probleme beim hochladen zu beheben, die sie möglicherweise erleben ein späterer leitfaden wird weiter diskutieren und vorlagen zeigen, wie man dateien mit parse speichern und anzeigen https //www back4app com/docs/flutter/parse sdk/flutter save file }]},{ 6 geopoint parse ermöglicht es ihnen, reale breiten und längengradkoordinaten mit einem objekt über seinen geopoint datentyp zu verknüpfen das hinzufügen eines parsegeopoint zu einem parseobject ermöglicht es abfragen, die nähe eines objekts zu einem referenzpunkt zu berücksichtigen beispiel // anfrage nach berechtigung hier und erhalt des aktuellen standorts das `position` objekt // geopoint objekt erstellen final geopoint = parsegeopoint(latitude position latitude, longitude position longitude); // ein objekt mit dem geopoint erstellen final gamepoint = parseobject('gamepoint') set('name', 'aktueller standort') set('location', geopoint); // speichern sie den geopoint in einem feld final response = await gamepoint save(); sie finden ein eigenständiges beispiel zum speichern des geopoint standorts in dieser main dart https //github com/templates back4app/flutter datatypes/blob/18c4c372eb49c1cd950eeaac355564134a5e70c4/lib/src/main dart datei vollständiges app beispiel dieses beispiel zeigt, wie man erstellen, löschen und aktualisieren sie ein gamepoint parse objekt verarbeiten sie verschiedene datentypen, einschließlich strings, doubles, booleans, dateien, geopunkte, listen und daten auf ios müssen sie ihrem simulator die erforderlichen zugriffsberechtigungen gewähren ios bietet einen entwicklerleitfaden zu geschützten ressourcen die beispielanwendungen in diesem leitfaden benötigen die standort https //developer apple com/documentation/bundleresources/information property list/nslocationwheninuseusagedescription und fotos https //developer apple com/documentation/bundleresources/information property list/nsphotolibraryaddusagedescription berechtigungs schlüssel, die in diesem leitfaden zu finden sind, um zu funktionieren fügen sie die schlüssel zur info plist datei hinzu, die sich befindet unter /ios/runner/info plist sie können den obigen schritt überspringen, wenn sie ihre flutter app im web ausführen 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; } } dieser code initialisiert das parse sdk in flutter, richtet die hauptanwendung ein und zeigt eine einfache startseite mit einem titel an fazit in diesem leitfaden haben sie über parseobjects und die verschiedenen datentypen, die parse zur verfügung stehen, gelernt sie haben auch gelernt, wie man operationen wie das speichern und abrufen der datentypen von und zu ihrem back4app backend durchführt