Flutter
GraphQL
GraphQL-Mutationen in Flutter: Ein CRUD-App-Beispiel
18 min
flutter crud app beispiel mit graphql einführung in unserem ersten flutter graphql leitfaden haben wir gelernt, wie man ein flutter projekt mit der graphql api einrichtet, um einfache daten auf back4app zu verbinden und abzufragen außerdem, wie wir den back4app graphql playground nutzen können, um abfragen/mutationen auszuführen, um die app datenbank zu erstellen/zu befüllen in diesem tutorial werden wir eine funktion hinzufügen, mit der wir direkt daten aus unserem back4app backend über unsere app mithilfe von graphql mutationen erstellen, aktualisieren und löschen können ziele am ende dieses artikels erwarten wir, dass sie in der lage sind daten in unserem backend mit der graphql api zu erstellen daten aus unserem backend mit der graphql api zu aktualisieren vorhandene daten aus dem backend mit der graphql api zu löschen voraussetzungen um dieses tutorial abzuschließen, benötigen sie sie müssen unseren vorherigen leitfaden lesen „flutter graphql projekt“ um unseren ausgangspunkt in diesem leitfaden zu verstehen wir werden das vorherige projekt verwenden, wenn sie es nicht haben, können sie es hier herunterladen eine ide zum schreiben von flutter code wie android studio oder vs code ein back4app konto, das hier erstellt werden kann back4app graphql flutter abhängigkeit https //pub dev/packages/graphql flutter hinweis wenn sie ein besseres verständnis der back4app graphql api haben möchten, werfen sie einen blick auf unser graphql kochbuch https //www back4app com/docs/parse graphql/graphql getting started und überprüfen sie auch unser graphql schema in unserem api playground 1 gui einrichten erstellen sie eine neue datei mutation page dart mutation page dart hier werden wir unsere gui erstellen, um eingaben vom benutzer zu erhalten und mutationsaufgaben durchzuführen fügen sie nun den folgenden code in mutation page dart mutation page dart ein 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 senddatabuttonpressed (){ 23 }, 24 deletedatabuttonpressed (){ 25 }, 26 updatebuttonpressed (){ 27 }, 28 ); 29 } 30 } appui() appui() widget wurde bereits für sie erstellt wir haben eine klasse namens mutationpage mutationpage erstellt und das appui appui widget als ihr widget zurückgegeben wir haben auch callback funktionen für unsere textfelder initialisiert, sodass der text im ersten textfeld in langname langname , der zweite in saveformat saveformat und objectid objectid aus dem letzten gespeichert wird fahren sie nun mit main dart main dart fort und fügen sie einen floatingactionbutton floatingactionbutton parameter im scaffold() scaffold() widget der myhomepage myhomepage klasse hinzu und übergeben sie den folgenden code 1 floatingactionbutton row( 2 mainaxisalignment mainaxisalignment end, 3 children \[ 4 floatingactionbutton( 5 herotag 'mutation page', 6 child text('m', 7 style textstyle( 8 color colors white, 9 ), 10 ), 11 onpressed (){ 12 navigator pushreplacement(context, materialpageroute( 13 builder ((context){ 14 return mutationpage(); 15 }) 16 )); 17 }, 18 ), 19 ], 20 ), dies wird einen floating button erstellen, der uns zur mutationpage() mutationpage() von unserer startseite navigiert jetzt ist unsere gui eingerichtet sie können ihre app jetzt hot restarten, um die gui zu sehen so sollte ihre main dart main dart aussehen 1 import 'package\ back4appgraphqldemo/mutation page dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ graphql flutter/graphql flutter dart'; 4 import 'consonents dart'; 5 import 'dart\ ui'; 6 7 void main() { 8 runapp(myapp()); 9 } 10 11 class myapp extends statelesswidget { 12 @override 13 widget build(buildcontext context) { 14 final httplink httplink = httplink( 15 uri 'https //parseapi back4app com/graphql', 16 headers { 17 'x parse application id' kparseapplicationid, 18 'x parse client key' kparseclientkey, 19 'x parse master key' kparsemasterkey, 20 //'x parse rest api key' kparserestapikey, 21 }, //getheaders() 22 ); 23 24 valuenotifier\<graphqlclient> client = valuenotifier( 25 graphqlclient( 26 cache optimisticcache(dataidfromobject typenamedataidfromobject), 27 link httplink, 28 ), 29 ); 30 31 return materialapp( 32 home graphqlprovider( 33 child myhomepage(), 34 client client, 35 ), 36 ); 37 } 38 } 39 40 class myhomepage extends statefulwidget { 41 @override 42 myhomepagestate createstate() => myhomepagestate(); 43 } 44 45 class myhomepagestate extends state\<myhomepage> { 46 string name; 47 string saveformat; 48 string objectid; 49 50 string query = ''' 51 query findlanguages{ 52 languages{ 53 count, 54 edges{ 55 node{ 56 name, 57 saveformat 58 } 59 } 60 } 61 } 62 '''; 63 64 @override 65 widget build(buildcontext context) { 66 return safearea( 67 child scaffold( 68 appbar appbar( 69 title text( 70 'parsing data using graphql', 71 ), 72 ), 73 floatingactionbutton row( 74 mainaxisalignment mainaxisalignment end, 75 children \[ 76 floatingactionbutton( 77 herotag 'mutation page', 78 child text('m', 79 style textstyle( 80 color colors white, 81 ), 82 ), 83 onpressed (){ 84 navigator pushreplacement(context, materialpageroute( 85 builder ((context){ 86 return mutationpage(); 87 }) 88 )); 89 }, 90 ), 91 ], 92 ), 93 body query( 94 options queryoptions( 95 documentnode gql(query), 96 ), 97 builder ( 98 queryresult result, { 99 refetch refetch, 100 fetchmore fetchmore, 101 }) { 102 if (result data == null) { 103 return center( 104 child text( 105 "loading ", 106 style textstyle(fontsize 20 0), 107 )); 108 } else { 109 return listview\ builder( 110 itembuilder (buildcontext context, int index) { 111 return listtile( 112 title text(result data\["languages"]\["edges"]\[index]\["node"] 113 \['name']), 114 trailing text(result data\["languages"]\["edges"]\[index] 115 \["node"]\['saveformat']), 116 117 ); 118 }, 119 itemcount result data\["languages"]\["edges"] length, 120 ); 121 } 122 }, 123 ), 124 ), 125 ); 126 } 127 } 2 erstellen/hinzufügen von daten zur datenbank wenn sie zu graphql configration dart graphql configration dart fortfahren, könnten sie sehen, dass wir bereits unseren graphqlclient graphqlclient eingerichtet haben und jetzt können wir ihn überall verwenden lassen sie uns fortfahren und eine datei database utils dart database utils dart erstellen und eine operation für erstellen von daten durchführen erstellen sie eine klasse databaseutils{} databaseutils{} und erstellen sie einen konstruktor, der die datenparameter erhält, mit denen wir arbeiten werden hier benötigen wir langname langname , saveformat saveformat , und objectid objectid 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 final string langname,saveformat,objectid; 6 databaseutils({this langname="",this saveformat="",this objectid=""}); 7 } erstellen sie eine funktion adddata() adddata() die eine asynchrone funktion zum erstellen von daten sein wird und unseren graphqlclient graphqlclient initialisiert, indem sie die graphqlconfigration graphqlconfigration klasse initialisiert fügen sie den folgenden code in die senddata() senddata() funktion ein 1 future\<queryresult> senddata() async{ 2 string adddata=''' 3 mutation createobject(\\$input createlanguagefieldsinput){ 4 createlanguage(input {fields \\$input}){ 5 language{ 6 name, 7 saveformat 8 } 9 } 10 } 11 '''; 12 final variable ={ 13 "input" { 14 "name" langname, 15 "saveformat" saveformat, 16 } 17 }; 18 19 graphqlconfiguration configuration = graphqlconfiguration(); 20 graphqlclient client = configuration clienttoquery(); 21 22 } hier haben wir eine variable initialisiert adddata adddata und die abfrage übergeben, um daten zu erstellen und variable variable zu initialisieren, die die abfragevariablen übergeben wird wir haben auch den graphqlclient graphqlclient initialisiert, der uns hilft, abfragen zu übergeben wir können die abfragen wie unten gezeigt übergeben 1 queryresult queryresult = await client query( 2 queryoptions(documentnode gql(adddata), variables variable), 3 ); 4 return queryresult; wir haben unsere graphqlclient graphqlclient instanz verwendet, um eine abfrage zu schreiben, die queryoptions() queryoptions() akzeptiert, die uns hilft, eine abfrage zu senden, wie sie im letzten tutorial gesehen haben das ergebnis wird in queryresult queryresult so sollte ihre database utils dart database utils dart aussehen 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 final string langname,saveformat,objectid; 6 databaseutils({this langname="",this saveformat="",this objectid=""}); 7 future\<queryresult> senddata() async{ 8 string adddata=''' 9 mutation createobject(\\$input createlanguagefieldsinput){ 10 createlanguage(input {fields \\$input}){ 11 language{ 12 name, 13 saveformat 14 } 15 } 16 } 17 '''; 18 final variable ={ 19 "input" { 20 "name" langname, 21 "saveformat" saveformat, 22 } 23 }; 24 25 graphqlconfiguration configuration = graphqlconfiguration(); 26 graphqlclient client = configuration clienttoquery(); 27 28 queryresult queryresult = await client query( 29 queryoptions(documentnode gql(adddata), variables variable), 30 ); 31 return queryresult; 32 } 33 } fahren sie nun mit ihrer ui klasse fort mutation page dart mutation page dart lassen sie uns den code für die schaltfläche daten senden schreiben, die innerhalb des senddatabuttonpressed senddatabuttonpressed parameters codiert werden kann da wir den langname und saveformat benötigen, überprüfen sie zuerst, ob sie nicht leer sind, und erstellen sie dann eine instanz von databaseutils databaseutils und übergeben sie die langname langname und saveformat saveformat parameter 1 if(langname isnotempty && saveformat isnotempty){ 2 utils = databaseutils( 3 langname langname, 4 saveformat saveformat , 5 ); 6 } rufen sie nach diesem aufruf die senddata() senddata() funktion von der databaseutils databaseutils instanz auf jetzt können sie hot restart app, füllen sie die beiden textfelder mit den entsprechenden daten aus und drücken sie die schaltfläche daten senden gehen sie jetzt zurück zu ihrer abfrage seite, indem sie die schwebende aktionsschaltfläche drücken, und sie könnten sehen, dass ein weiteres datum zu unserer tabelle hinzugefügt wurde so würde ihre mutationpage klasse aussehen 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 senddatabuttonpressed (){ 23 if(langname isnotempty && saveformat isnotempty){ 24 utils = databaseutils( 25 langname langname, 26 saveformat saveformat , 27 ); 28 utils senddata(); 29 } 30 }, 31 deletedatabuttonpressed (){ 32 }, 33 updatebuttonpressed (){ 34 }, 35 ); 36 } 37 } 3 daten aktualisieren in databaseutils databaseutils erstellen sie eine future future funktion updatedata() updatedata() initialisieren sie eine string update string update und übergeben sie die aktualisierungsabfrage und abfragevariablen in final variables final variables 1 future\<queryresult> updatedata() async{ 2 string update=''' 3 mutation updateobject(\\$id id!,\\$input updatelanguagefieldsinput){ 4 updatelanguage(input {id \\$id, fields \\$input}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 "input" { 15 "name" langname 16 } 17 }; 18 } jetzt initialisieren wir unseren graphqlclient graphqlclient und senden die abfrage durch queryoptions() queryoptions() so würde ihr code aussehen 1 future\<queryresult> updatedata() async{ 2 3 string update=''' 4 mutation updateobject(\\$id id!,\\$input updatelanguagefieldsinput){ 5 updatelanguage(input {id \\$id, fields \\$input}){ 6 language{ 7 name, 8 id 9 } 10 } 11 } 12 '''; 13 14 final variable={ 15 "id"\ objectid, 16 "input" { 17 "name" langname 18 } 19 }; 20 21 graphqlconfiguration configuration = graphqlconfiguration(); 22 graphqlclient client = configuration clienttoquery(); 23 24 queryresult queryresult = await client query( 25 queryoptions(documentnode gql(update), variables variable), 26 ); 27 return queryresult; 28 } kommen sie jetzt zurück zu mutaion page dart mutaion page dart und codieren sie im updatebuttonpressed updatebuttonpressed parameter überprüfen sie, ob langname langname , objectid objectid und saveformat saveformat nicht leer sind und rufen sie dann die updatedata() updatedata() funktion von databaseutils databaseutils klasse auf 1 updatebuttonpressed (){ 2 if(langname isnotempty && saveformat isnotempty && objectid isnotempty){ 3 utils = databaseutils( 4 langname langname, 5 saveformat saveformat , 6 objectid objectid 7 ); 8 utils updatedata(); 9 } 10 }, gehen sie zum back4app dashboard und wählen sie eine sprache aus, die sie aktualisieren möchten, und kopieren sie deren objectid hot restart ihre app und füllen sie alle 3 textfelder aus den neuen namen der sprache, die sie im ersten textfeld einfügen möchten, und das neue speicherformat im zweiten und objectid im dritten drücken sie jetzt die schaltfläche daten aktualisieren und überprüfen sie die aktualisierten informationen in der app, indem sie auf die schwebende aktionsschaltfläche q unten rechts klicken 4 daten löschen erstellen sie eine deletedata() deletedata() asynchron funktion in databaseutils databaseutils und initialisieren sie string delete string delete und übergeben sie die graphql abfrage zum löschen von daten nehmen sie finale variablen finale variablen und übergeben sie die abfragevariablen hinein 1 future\<queryresult> deletedata() async{ 2 string delete=''' 3 mutation deleteobject(\\$id id!){ 4 deletelanguage(input {id \\$id}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 }; 15 } hier benötigen wir nur die objectid objectid der zeile, die gelöscht werden muss initialisieren sie den graphqlclient graphqlclient und senden sie die abfrage über queryoptions() queryoptions() 1 future\<queryresult> deletedata() async{ 2 string delete=''' 3 mutation deleteobject(\\$id id!){ 4 deletelanguage(input {id \\$id}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 }; 15 16 graphqlconfiguration configuration = graphqlconfiguration(); 17 graphqlclient client = configuration clienttoquery(); 18 19 queryresult queryresult = await client query( 20 queryoptions(documentnode gql(delete), variables variable), 21 ); 22 23 return queryresult; 24 } in mutationpage mutationpage in der deletedatabuttonpressed deletedatabuttonpressed parameter überprüfen, ob objectid objectid nicht leer oder null ist und die deletedata() deletedata() funktion aufrufen hot restart anwendung, geben sie die objectid der zu löschenden zeile ein und drücken sie die delete data schaltfläche es sollte eine bestimmte zeile aus ihrer language language klasse löschen erfolg ihre app hat endlich ihre mutationsoperationen durchgeführt !!! main dart main dart sollte so aussehen 1 import 'package\ back4appgraphqldemo/mutation page dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ graphql flutter/graphql flutter dart'; 4 import 'consonents dart'; 5 import 'dart\ ui'; 6 7 void main() { 8 runapp(myapp()); 9 } 10 11 class myapp extends statelesswidget { 12 @override 13 widget build(buildcontext context) { 14 final httplink httplink = httplink( 15 uri 'https //parseapi back4app com/graphql', 16 headers { 17 'x parse application id' kparseapplicationid, 18 'x parse client key' kparseclientkey, 19 'x parse master key' kparsemasterkey, 20 //'x parse rest api key' kparserestapikey, 21 }, //getheaders() 22 ); 23 24 valuenotifier\<graphqlclient> client = valuenotifier( 25 graphqlclient( 26 cache optimisticcache(dataidfromobject typenamedataidfromobject), 27 link httplink, 28 ), 29 ); 30 31 return materialapp( 32 home graphqlprovider( 33 child myhomepage(), 34 client client, 35 ), 36 ); 37 } 38 } 39 40 class myhomepage extends statefulwidget { 41 @override 42 myhomepagestate createstate() => myhomepagestate(); 43 } 44 45 class myhomepagestate extends state\<myhomepage> { 46 string name; 47 string saveformat; 48 string objectid; 49 50 string query = ''' 51 query findlanguages{ 52 languages{ 53 count, 54 edges{ 55 node{ 56 name, 57 saveformat 58 } 59 } 60 } 61 } 62 '''; 63 64 @override 65 widget build(buildcontext context) { 66 return safearea( 67 child scaffold( 68 appbar appbar( 69 title text( 70 'parsing data using graphql', 71 ), 72 ), 73 floatingactionbutton row( 74 mainaxisalignment mainaxisalignment end, 75 children \[ 76 floatingactionbutton( 77 herotag 'mutation page', 78 child text('m', 79 style textstyle( 80 color colors white, 81 ), 82 ), 83 onpressed (){ 84 navigator pushreplacement(context, materialpageroute( 85 builder ((context){ 86 return mutationpage(); 87 }) 88 )); 89 }, 90 ), 91 ], 92 ), 93 body query( 94 options queryoptions( 95 documentnode gql(query), 96 ), 97 builder ( 98 queryresult result, { 99 refetch refetch, 100 fetchmore fetchmore, 101 }) { 102 if (result data == null) { 103 return center( 104 child text( 105 "loading ", 106 style textstyle(fontsize 20 0), 107 )); 108 } else { 109 return listview\ builder( 110 itembuilder (buildcontext context, int index) { 111 return listtile( 112 title text(result data\["languages"]\["edges"]\[index]\["node"] 113 \['name']), 114 trailing text(result data\["languages"]\["edges"]\[index] 115 \["node"]\['saveformat']), 116 117 ); 118 }, 119 itemcount result data\["languages"]\["edges"] length, 120 ); 121 } 122 }, 123 ), 124 ), 125 ); 126 } 127 } database utils dart database utils dart sollte so aussehen 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 6 final string langname,saveformat,objectid; 7 8 databaseutils({this langname="",this saveformat="",this objectid=""}); 9 10 string delete=''' 11 mutation delete languages(\\$id id!){ 12 deletelanguage(input {id \\$id}){ 13 language{ 14 name, 15 id 16 } 17 } 18 } 19 '''; 20 21 string adddata=''' 22 mutation create languages(\\$input createlanguagefieldsinput){ 23 createlanguage(input {fields \\$input}){ 24 language{ 25 name, 26 saveformat 27 } 28 } 29 } 30 '''; 31 string update=''' 32 mutation update languages(\\$id id!,\\$input updatelanguagefieldsinput){ 33 updatelanguage(input {id \\$id, fields \\$input}){ 34 language{ 35 name, 36 id 37 } 38 } 39 } 40 '''; 41 42 future\<queryresult> senddata() async{ 43 44 final variable ={ 45 "input" { 46 "name" langname, 47 "saveformat" saveformat, 48 } 49 }; 50 print('sendingdata'); 51 52 graphqlconfiguration configuration = graphqlconfiguration(); 53 graphqlclient client = configuration clienttoquery(); 54 55 queryresult queryresult = await client query( 56 queryoptions(documentnode gql(adddata), variables variable), 57 ); 58 return queryresult; 59 60 } 61 future\<queryresult> updatedata() async{ 62 final variable={ 63 "id"\ objectid, 64 "input" { 65 "name" langname 66 } 67 }; 68 69 graphqlconfiguration configuration = graphqlconfiguration(); 70 graphqlclient client = configuration clienttoquery(); 71 72 queryresult queryresult = await client query( 73 queryoptions(documentnode gql(update), variables variable), 74 ); 75 return queryresult; 76 } 77 78 79 future\<queryresult> deletedata() async{ 80 final variable={ 81 "id"\ objectid, 82 }; 83 84 graphqlconfiguration configuration = graphqlconfiguration(); 85 graphqlclient client = configuration clienttoquery(); 86 87 queryresult queryresult = await client query( 88 queryoptions(documentnode gql(delete), variables variable), 89 ); 90 91 return queryresult; 92 } 93 } mutaion page dart mutaion page dart sollte so aussehen 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 23 senddatabuttonpressed (){ 24 if(langname isnotempty && saveformat isnotempty){ 25 utils = databaseutils( 26 langname langname, 27 saveformat saveformat , 28 ); 29 utils senddata(); 30 } 31 }, 32 deletedatabuttonpressed (){ 33 if(objectid isnotempty){ 34 utils = databaseutils( 35 objectid objectid, 36 ); 37 utils deletedata(); 38 } 39 }, 40 updatebuttonpressed (){ 41 if(langname isnotempty && saveformat isnotempty && objectid isnotempty){ 42 utils = databaseutils( 43 langname langname, 44 saveformat saveformat , 45 objectid objectid 46 ); 47 utils updatedata(); 48 } 49 }, 50 ); 51 } 52 } fazit in diesem leitfaden haben wir graphql mutationen in der flutter app verwendet, um neue objekte auf back4app zu erstellen; objekte auf back4app zu aktualisieren; objekte auf back4app zu löschen an diesem punkt haben sie ein voll funktionsfähiges flutter graphql crud projekt, das sie als ausgangspunkt verwenden können, um ihre nächste app zu entwickeln im nächsten leitfaden werden wir tief in abfragen eintauchen und zeigen, wie man sie erstellt, um daten von back4app abzurufen und in unserer flutter app anzuzeigen haben sie einen großartigen tag!