Flutter GraphQL project using Back4App

Introduction

In this tutorial, we’re 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;
  • Query data from GraphQL API;
  • Fetch data in your Flutter App;

Prerequisites

In order 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 dependency.

Step 1: Clone project from Github to Android Studio

Go to the Github repo , 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 file. You will see 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 should look like this.

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 file and our important values are stored in consonents.dart and we can directly use it from there. We will require the graphql_flutter Dependency to use graphQL in our app.

The graphql_flutter is most popular GraphQL client for flutter. It helps us to use GraphQL queries directly in our code. It provides us with GraphQLClient, 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. The package provides us with plenty of features including:

  • Subscriptions
  • In memory cache
  • Offline cache sync
  • Optimistic results
  • Graph1l file uploads

You can import it by writing the following code in pubspec.yaml file:

dependencies:
graphql_flutter: ^3.1.0

See more about graphql_flutter at GraphQL Flutter Documentation

All dependencies are now pre-installed and you are ready to proceed to the next step.

Step 2 : Creating backend in Back4App

After you have signed up at Back4App website you can proceed to the next step and create a new app. Click on ‘Build new App’ box. Give it the same name as your project name which over here is back4app_Graphql’. You will now see your dashboard after loading process is completed.

Now scroll down to Server Settings on your left and select Settings in the Manage Parse Server Card, then select the option ‘3.10.0 — Parse Server 3.10.0’ from the list. Now press the save button and wait until it gets saved.

Now come back to Core Menu(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.

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 :

mutation CreateClass {
createClass(input:{
name: "Language"
schemaFields: {
addStrings: [{name: "name"}{name: "saveFormat"}]
}
}){
class{
schemaFields{
name
__typename
}
}
}
}

The code above will create a class named “Language”. Let's populate this new class with some rows:

mutation CreateObject{
createLanguage(input:{fields: {name: "Python", saveFormat:".py"}}){
language{
name,
saveFormat
}
}
}

If your operation is successful you'll see this message on the right code-box on GraphQL PlayGround:

{
"data": {
"createLanguage": {
"language": {
"name": "Python",
"saveFormat": ".py"
}
}
}
}

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”.

Now let’s see all the data in our class Languages. To retrieve the data we use a query. So go ahead and type the below command:

query FindLanguages{
languages{
count,
edges{
node{
name,
saveFormat
}
}
}
}

In query FindLanguage 'FindLanguage' is just a name for your query command and you could even name it anything else. We use the find(className: "") command to find all the elements of the specific Class. Count, returns the number of elements in the Class and all the elements are shown inside the result object. The above query is going to return this:

{
"data": {
"languages": {
"count": 3,
"edges": [
{
"node": {
"name": "Python",
"saveFormat": ".py"
}
},
{
"node": {
"name": "C",
"saveFormat": ".c"
}
},
{
"node": {
"name": "Java",
"saveFormat": ".java"
}
}
]
}
}
}

You see all other queries in the following link: GraphQL queries — Back4App. Now let's proceed to the next step.

Step 4 : Setting up GraphQL in our App

Let's start coding our app. Before this, you need to do few things in your lib\consonents.dart file:

  1. Copy graphql link which is next to the history button in the top of GraphQL window, and paste it in as kUrl string datatype.
  2. Now move to 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 file:

The file should have following code:

String kParseApplicationId= "APPLICATION_ID_COPIED_FROM_HEADERS";
String kParseClientKey = "CLIENT_KEY_COPIED_FROM_HEADER";
String kParseMasterKey = "MASTER_KEY_COPIED_FROM_HEADER";
String kUrl= "URL_COPIED";
// replace "APPLICATION_ID_COPIED_FROM_HEADERS", //"CLIENT_KEY_COPIED_FROM_HEADER", //"MASTER_KEY_COPIED_FROM_HEADER",
//"URL_COPIED" with real keys/ids copied

//from Http Headers tab.

Now go to main.dart file and head over to MyApp Stateless Widget and add the following code just above the return MaterialApp():

final HttpLink httpLink = HttpLink(
uri: kUrl,
headers: {
'X-Parse-Application-Id' : kParseApplicationId,
'X-Parse-Client-Key' : kParseClientKey,
'X-Parse-Master-Key': kParseMasterKey,
},
);

HttpLink* is from 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.:

ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
cache: OptimisticCache(dataIdFromObject: typenameDataIdFromObject),
link: httpLink,
),
);

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:

Let’s call the API and get the data

Step 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:

String query='''
query FindLanguages{
languages{
count,
edges{
node{
name,
saveFormat
}
}
}
}
''';

Now go to Query() widget, inside the body parameter of the Scaffold, which has two properties:

  • options
  • builder

And then pass null for both. This is how your build method would look like:

Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Parsing data using GraphQL',
),
),
body: Query(
options: null,
builder: null
),
),);
}

The 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:

options: QueryOptions(
documentNode: gql(query),
),

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 .
So let's code the following below:

builder : (QueryResult result, { Refetch refetch,FetchMore fetchMore,})
{
if(result.data==null){
return Center(child: Text("Loading...",style: TextStyle(fontSize: 20.0),));
}else{
return Text('SUCCESS');
}
},

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 class in main.dart should look like:

Now start the App and wait for a few seconds after it restarts. If you see ‘SUCCESS’ on the screen:

Congrats! You have established your connection and called the API.

Step 6: Getting and showing Data from API

Now, instead of returning the Text widget we will be returning the ListView.builder() widget with original Data. Write the following code instead of return Text('SUCCESS').

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:

{
"data": {
"languages": {
"count": 3,
"edges": [
{
"node": {
"name": "Python",
"saveFormat": ".py"
}
},
{
"node": {
"name": "C",
"saveFormat": ".c"
}
},
{
"node": {
"name": "Java",
"saveFormat": ".java"
}
}
]
}
}
}

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 symbolises 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 we enter the "data" location. So to give the other locations we add ["location_name"]. to it. So the locaion of "Python" will be result.data["languages"]["edges"][0]["node"]['name'].

When using ListView, it takes two parameters, itemCount, it tells the no of elements in the API call, itemBuilder, it takes a function with parameters (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:

Now when we replace Text('SUCCESS') with the above ListView.builder() widget, we first pass the itemCount where we pass the no 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" of the "Languages" class and in "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 should look like now:

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 !

Originally published at https://www.back4app.com.

Store and query relational data on the cloud. Make it accessible over GraphQL and REST with a scalable, open-source backend, based on the Parse Platform.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store