Flutter
GraphQL
Start from Template
28 min
download a flutter graphql project with source code and start using back4app introduction in this tutorial, we are going to build an application that would parse data from back4app backend through graphql as you may know, graphql is an open source data query and manipulation language for apis, and a runtime for fulfilling queries with existing data back4app is a low code backend as a service(based on open source parse platform) which is helping developers to build extensible and scalable mobile and web applications at a rapid pace goals the main goal is to build a simple app that is going to show a list of programming languages and their save type format at the end of this article we expect that you will be able to make an api call on back4app using graphql; get the data from graphql api; fetch data in your flutter app prerequisites to complete this tutorial, you will need an ide for writing flutter code like android studio or flutter however we will be using android studio for this tutorial a back4app account that can be created here back4app graphql flutter https //pub dev/packages/graphql flutter 1 clone project from github to android studio go to the github repo https //github com/templates back4app/flutter graphql , and download the zip file, extract it, and open it in your flutter ide to complete this step, drag the folder inside the zip file into your desktop, open android studio and then click on open existing android studio project the project directory over would be usually ‘ c \users\username\desktop\back4app graphql starting code ’ but this may be different for different users open the project and go to the lib\main dart lib\main dart file you will see so many errors there, don’t worry, just press all ‘ get dependencies ’ and all the errors would perish if doesn’t then just press ‘ upgrade dependencies ’ the code in your main dart main dart should look like this 1 import 'package\ flutter/material dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 import 'consonents dart'; 4 5 void main() { 6 runapp(myapp()); 7 } 8 9 class myapp extends statelesswidget { 10 @override 11 widget build(buildcontext context) { 12 return materialapp( 13 home myhomepage(), 14 ), 15 ); 16 } 17 } 18 class myhomepage extends statefulwidget { 19 @override 20 myhomepagestate createstate() => myhomepagestate(); 21 } 22 23 class myhomepagestate extends state\<myhomepage> { 24 25 @override 26 widget build(buildcontext context) { 27 return safearea( 28 child scaffold( 29 appbar appbar( 30 title text('parsing data using graphql', 31 ), 32 ), 33 body container(), 34 ),); 35 } 36 } if you open run the app now you would only see an empty screen in your emulator/device with only an appbar titled ‘parsing data using graphql’ we will work on main dart main dart file and our important values are stored in consonents dart consonents dart and we can directly use it from there we will require the graphql flutter graphql flutter dependency to use graphql in our app the graphql flutter graphql flutter is most popular graphql cliet for flutter it helps us to use graphql queries directly in our code it provides us with graphqlclient graphqlclient , graphqlprovider graphqlprovider and many other useful widgets that helps us to parse data from our database directly with the help of graphql without even using streambuilder streambuilder the package provides us with plenty of features including subscriptions in memory cache offline cache sync optimistic results graphql file uploads you can import it by writing the following code in pubspec yaml pubspec yaml file see more about graphql flutter graphql flutter at graphql flutter documentation all dependencies are already pre installed and you are good to proceed to the next step now 2 creating backend in back4app after you have signed up at back4app https //www back4app com/ website, u can proceed to the next step and create a new app click on ‘build new app’ give it the same name as your project name which over here is ‘back4app graphql’ now scroll down to server settings on your left and select settings manage parse server card, then select the option ‘3 10 0 parse server 3 10 0’ from the list now press the save button below and wait until it gets saved now come back to core (on the left), select the api console , and select graphql console from it this is the window where you can write and test your graphql queries/mutations code let’s proceed to the next step 3 creating and getting data through graphql now, let’s test the graphql api on back4app using the graphql api console first, paste the following query on the left code box 1 mutation createclass { 2 createclass(input { 3 name "language" 4 schemafields { 5 addstrings \[{name "name"}{name "saveformat"}] 6 } 7 }){ 8 class{ 9 schemafields{ 10 name 11 typename 12 } 13 } 14 } 15 } 16 the code above will create a class named “language” let’s populate this new class with some rows 1 mutation createobject{ 2 createlanguage(input {fields {name "python", saveformat " py"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } if your operation is successful you’ll see this message on the right code box on graphql playground 1 { 2 "data" { 3 "createlanguage" { 4 "language" { 5 "name" "python", 6 "saveformat" " py" 7 } 8 } 9 } 10 } mutations are used to create or make changes on a class by running the above mutation, we’ll create a new class named language with data fields name “python” saveformat “ py” repeat the process and create two more objects in the same class for name “c” and saveformat “ c” name “java” and saveformat “ java” the mutation for this will be such 1 mutation createobject{ 2 createlanguage(input {fields {name "c", saveformat " c"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } java 1 mutation createobject{ 2 createlanguage(input {fields {name "java", saveformat " java"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } now let’s see all the data in our class languages for reading data we use query so go ahead and type the below command 1 query findlanguages{ 2 languages{ 3 count, 4 edges{ 5 node{ 6 name, 7 saveformat 8 } 9 } 10 } 11 } in query findlanguage query findlanguage ‘findlanguage’ is just a name for your query command and you could even name it anything else we use the find(classname "") find(classname "") command to find all the elements of the specific class count count , returns the number of elements in the class and all the elements are shown inside the result result object the above query is going to return this 1 { 2 "data" { 3 "languages" { 4 "count" 3, 5 "edges" \[ 6 { 7 "node" { 8 "name" "python", 9 "saveformat" " py" 10 } 11 }, 12 { 13 "node" { 14 "name" "c", 15 "saveformat" " c" 16 } 17 }, 18 { 19 "node" { 20 "name" "java", 21 "saveformat" " java" 22 } 23 } 24 ] 25 } 26 } 27 } you can see all other queries in the following link graphql queries back4app https //blog back4app com/graphql on parse/ now, let’s proceed to the next step 4 setting up graphql in our app let’s start coding our app before this, you must do few things in your lib\consonents dart lib\consonents dart file copy graphql link which is next to the history button in the top of graphql window, and paste it in as kurl string datatype now move to the bottom of the page and copy the codes from http headers, copy only the codes on the right of the colon( ) and paste them with their respective names in the lib\consonents dart lib\consonents dart file the file should have following code 1 string kparseapplicationid= "application id copied from headers"; 2 string kparseclientkey = "client key copied from header"; 3 string kurl= "url copied"; 4 // replace "application id copied from headers", "client key copied from header", "url copied" with real keys/ids copied 5 //from http headers tab now move to main dart main dart file and head over to myapp stateless widget and add the following code just above the return return materialapp() materialapp() 1 final httplink httplink = httplink( 2 uri kurl, 3 headers { 4 'x parse application id' kparseapplicationid, 5 'x parse client key' kparseclientkey, 6 }, 7 ); httplink is from flutter graphql dart and takes the widget httplink() with two parameters the first is the graphql api url on back4app the second are the headers necessary to authenticate on back4app api after this section you need to include the graphql client code (explain what is), copy the code below and then paste under the httplink section 1 valuenotifier\<graphqlclient> client = valuenotifier( 2 graphqlclient( 3 cache optimisticcache(dataidfromobject typenamedataidfromobject), 4 link httplink, 5 ), 6 ); now we’ve provided the link and cache method to our graphqlclient we have done this through our valuenotifier and named it as client let’s wrap the myhomepage() widget which is a child of materialapp with graphqlprovider and pass myhomepage() as its client add an another parameter inside graphqlprovider namely client and pass client(name of our valuenotifier) in it this is how your myapp class should look now 1 class myapp extends statelesswidget { 2 @override 3 widget build(buildcontext context) { 4 final httplink httplink = httplink( 5 uri kurl, 6 headers { 7 'x parse application id' kparseapplicationid, 8 'x parse client key' kparseclientkey, 9 //'x parse rest api key' kparserestapikey, 10 },//getheaders() 11 ); 12 valuenotifier\<graphqlclient> client = valuenotifier( 13 graphqlclient( 14 cache optimisticcache(dataidfromobject typenamedataidfromobject), 15 link httplink, 16 ), 17 ); 18 return materialapp( 19 home graphqlprovider( 20 child myhomepage(), 21 client client, 22 ), 23 ); 24 } 25 } let’s call the api and get the data 5 making an api call now we will work on the myhomepagestate we’re going to start by initialising a string data type named ‘query’ and assign/pass the query statement for finding all the data from our language class to it since the query is multi line, we will pass the query in triple quotes here’s how it looks like 1 string query=''' 2 query findlanguages{ 3 languages{ 4 count, 5 edges{ 6 node{ 7 name, 8 saveformat 9 } 10 } 11 } 12 } 13 '''; now go to query() widget, inside the body parameter of the scaffold which have two properties options builder and then pass null for both this is how your build method would look like 1 widget build(buildcontext context) { 2 return safearea( 3 child scaffold( 4 appbar appbar( 5 title text('parsing data using graphql', 6 ), 7 ), 8 body query( 9 options null, 10 builder null 11 ), 12 ),); 13 } the query() query() widget helps us write queries for graphql and will help us read and get data we will pass the query statement which we have taken as a string in the options and build the widget with the builder parameter so pass the queryoptions() widget in options as follows 1 options queryoptions( 2 documentnode gql(query), 3 ), 4 the query is passed through documentnode parameter in queryoptions now let’s build with the help of builder parameter the builder method accepts a function with three parameters namely, queryresult result; refetch refetch; fetchmore fetchmore right now, we only need to worry about the queryresult which gives us the result of our query and we can access the data through result data result data so let’s code the following below 1 builder (queryresult result, { refetch refetch,fetchmore fetchmore,}) 2 { 3 if(result data==null){ 4 return center(child text("loading ",style textstyle(fontsize 20 0),)); 5 }else{ 6 return text('success'); 7 } 8 }, in the above code we are accessing the data if there’s no data we return a text widget reading ‘loading…’ else we will return a text() widget reading ‘success’ here’s how your myhomepage myhomepage class in main dart main dart should look like 1 class myhomepage extends statefulwidget { 2 @override 3 myhomepagestate createstate() => myhomepagestate(); 4 } 5 6 class myhomepagestate extends state\<myhomepage> { 7 string name; 8 string saveformat; 9 string objectid; 10 11 string query = ''' 12 query findlanguages{ 13 languages{ 14 count, 15 edges{ 16 node{ 17 name, 18 saveformat 19 } 20 } 21 } 22 } 23 '''; 24 25 @override 26 widget build(buildcontext context) { 27 return safearea( 28 child scaffold( 29 appbar appbar( 30 title text( 31 'parsing data using graphql', 32 ), 33 ), 34 body query( 35 options queryoptions( 36 documentnode gql(query), 37 ), 38 builder ( 39 queryresult result, { 40 refetch refetch, 41 fetchmore fetchmore, 42 }) { 43 if (result data == null) { 44 return center( 45 child text( 46 "loading ", 47 style textstyle(fontsize 20 0), 48 ), 49 ); 50 } else{ 51 return text('success'); 52 } 53 } 54 ), 55 ), 56 ); 57 } 58 } now, start the app and wait for a few seconds after it restarts if you see ‘success’ on the screen then congrats! you have established your connection and called the api 6 getting and showing data from api instead of returning the text widget, we will return the listview\ builder() widget with original data write the following code instead of return text('success') text('success') 1 return listview\ builder( 2 itembuilder (buildcontext context, int index){ 3 return listtile( 4 title text(result data\["languages"]\["edges"]\[index]\["node"]\['name']), 5 trailing text(result data\["languages"]\["edges"]\[index]\["node"]\['saveformat']), 6 ); 7 }, 8 itemcount result data\["languages"]\["edges"] length, 9 ); now if you look back to your graphql result screen in your api console of back4app where we typed our find method, the results were such 1 { 2 "data" { 3 "languages" { 4 "count" 3, 5 "edges" \[ 6 { 7 "node" { 8 "name" "python", 9 "saveformat" " py" 10 } 11 }, 12 { 13 "node" { 14 "name" "c", 15 "saveformat" " c" 16 } 17 }, 18 { 19 "node" { 20 "name" "java", 21 "saveformat" " java" 22 } 23 } 24 ] 25 } 26 } 27 } so from above code the location of “python” was “data” > “ languages” > “count” > “edges” > “node” > “name” also notice name is inside square brackets ‘\[]’ of edges which symbolizes it is the first element of edges list/array so we need to enter into this location to get “python” and same for everything else when we write result data result data , we enter the “data” location so to give the other locations we add \["location name"] \["location name"] to it so the location of “python” will be result data\["languages"]\["edges"]\[0]\["node"]\["name"] result data\["languages"]\["edges"]\[0]\["node"]\["name"] when using listview listview , it takes two parameters, itemcount itemcount , it tells the number of elements in the api call, itembuilder itembuilder , it takes a function with parameters (buildcontext context, int index) (buildcontext context, int index) and returns a list widgets in which we will be showing the data here, we will use list of listtile to show the data 1 return listview\ builder( 2 itemcount result data\["languages"]\["edges"] length, 3 itembuilder (buildcontext context, int index){ 4 return listtile( 5 title text(result data\["languages"]\["edges"]\[index]\["node"]\['name']), 6 trailing text(result data\["languages"]\["edges"]\[index]\["node"]\['saveformat']), 7 ); 8 }, 9 10 ); when we replace text('success') text('success') with the above listview\ builder() widget, we first pass the itemcount where we pass the number of elements in the results list and so we don’t need to worry about that anymore in itembuilder we are returning a list of listtiles which will have the "name" "name" of the "languages" "languages" class and in "saveformat" "saveformat" in the trailing notice we used index instead of any number after result, this is what itemcount took care of this is how your main dart main dart should look like now 1 import 'package\ flutter/material dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 import 'consonents dart'; 4 import 'dart\ ui'; 5 6 void main() { 7 runapp(myapp()); 8 } 9 10 class myapp extends statelesswidget { 11 @override 12 widget build(buildcontext context) { 13 final httplink httplink = httplink( 14 uri 'https //parseapi back4app com/graphql', 15 headers { 16 'x parse application id' kparseapplicationid, 17 'x parse client key' kparseclientkey, 18 }, //getheaders() 19 ); 20 21 valuenotifier\<graphqlclient> client = valuenotifier( 22 graphqlclient( 23 cache optimisticcache(dataidfromobject typenamedataidfromobject), 24 link httplink, 25 ), 26 ); 27 28 return materialapp( 29 home graphqlprovider( 30 child myhomepage(), 31 client client, 32 ), 33 ); 34 } 35 } 36 37 class myhomepage extends statefulwidget { 38 @override 39 myhomepagestate createstate() => myhomepagestate(); 40 } 41 42 class myhomepagestate extends state\<myhomepage> { 43 string name; 44 string saveformat; 45 string objectid; 46 47 string query = ''' 48 query findlanguages{ 49 languages{ 50 count, 51 edges{ 52 node{ 53 name, 54 saveformat 55 } 56 } 57 } 58 } 59 '''; 60 61 @override 62 widget build(buildcontext context) { 63 return safearea( 64 child scaffold( 65 appbar appbar( 66 title text( 67 'parsing data using graphql', 68 ), 69 ), 70 body query( 71 options queryoptions( 72 documentnode gql(query), 73 ), 74 builder ( 75 queryresult result, { 76 refetch refetch, 77 fetchmore fetchmore, 78 }) { 79 if (result data == null) { 80 return center( 81 child text( 82 "loading ", 83 style textstyle(fontsize 20 0), 84 )); 85 } else { 86 return listview\ builder( 87 itembuilder (buildcontext context, int index) { 88 return listtile( 89 title text(result data\["languages"]\["edges"]\[index]\["node"] 90 \['name']), 91 trailing text(result data\["languages"]\["edges"]\[index] 92 \["node"]\['saveformat']), 93 ); 94 }, 95 itemcount result data\["languages"]\["edges"] length, 96 ); 97 } 98 }, 99 ), 100 ), 101 ); 102 } 103 } and our final app screen conclusion now you have a flutter app connected to a graphql api that can store and retrieve data on back4app we did not require to encode or decode the json data separately which makes our work easier and faster using few lines of codes have a great day!