My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Build a simple mobile app with Graphql and Flutter

Build a simple mobile app with Graphql and Flutter

mamus eferha's photo
mamus eferha
·Jan 31, 2021·

7 min read

Graphql is a query language for APIs that gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools. It uses one endpoint, and users can structure their query such that they only fetch exactly what they need at a time.

In this article, I have built a mobile app that queries a graphql API and returns a list of continents and countries in the world. You can find the API here => countries.trevorblades.com.

For this project, we will utilize the following packages in our app

graphql_flutter

provider

Create a new flutter project and add these packages to your pubspec.yaml file in the root directory.

Next, create the following folders/files in your lib folder; Models, Queries, Services, UI, Utils, config.dart. Your lib folder should look like this;

Lib 
 - Models
 - Queries
 - Services
 - UI
 - Utils
 - config.dart
 - main.dart

Set-up graphql

The next step after creating your folders is to set up graphql, open your config.dart, and paste the following code

import 'package:countries_graphql_tutorial/Models/continents_model.dart';
import 'package:countries_graphql_tutorial/Queries/queries.dart';
import 'package:countries_graphql_tutorial/config.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

class ApiService {
  GraphQLConfiguration graphQLConfiguration = GraphQLConfiguration();
  AllQueries allQueries = AllQueries();

  Future<Data> getContinents() async {
    try {
      GraphQLClient _client = graphQLConfiguration.clientToQuery();
      QueryResult result = await _client
          .query(QueryOptions(documentNode: gql(allQueries.continentsQuery())));
      if (result.hasException) {
        print(result.exception.toString());
        return null;
      }
      var response = result.data.data;
      final map = response as Map<String, dynamic>;
      Data mappedResult = Data.fromJson(map);
      return mappedResult;
    } catch (e) {
      print(e);
      return null;
    }
  }
}

Our single endpoint/uri for the project is ‘trevorblades.com’, as I said earlier graphql has only one endpoint where all requests are made, unlike rest API which utilizes different uri for different calls.

GraphqlConfiguration class is where our graphql connection is being made, and it has a single method, clientToQuery().

Writing your queries

Next is to write your graphql query, if you’re just starting with graphql, you can visit their official site to learn how to write queries and mutations graphql.org.

The query for this project should be in your Queries folder, create a file called queries.dart, and paste the following code.

class AllQueries {
String continentsQuery() {
return """
query Continent{
    continents{
     code
      name
      countries{
        code
        name
        phone
        capital
        currency
        languages{
          name
        }
        states{
          name
        }
      }
    }
   }
""";
}
}

This is the only query in our app, and it fetches all the continents as well as the countries under them.

Model class

After writing your query, paste it on the playground — countries.trevorblades.com and run.

1_0rnn6545J7p1VGQlrw2euA.png

You should get a response on the second panel. Create a JSON to dart model class manually from the response under Models/continent_models.dart or use app.quicktype.io. It automatically creates a model class for you in different languages, paste the query response, select dart and copy the result.

Stringing it all together, Service class

Now that you have your model and query file ready, you can now write your service class. Create a file under services called continent_service.dart and paste the following code.

import 'package:countries_graphql_tutorial/Models/continents_model.dart';
import 'package:countries_graphql_tutorial/Queries/queries.dart';
import 'package:countries_graphql_tutorial/config.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

class ApiService {
  GraphQLConfiguration graphQLConfiguration = GraphQLConfiguration();
  AllQueries allQueries = AllQueries();

  Future<Data> getContinents() async {
    try {
      GraphQLClient _client = graphQLConfiguration.clientToQuery();
      QueryResult result = await _client
          .query(QueryOptions(documentNode: gql(allQueries.continentsQuery())));
      if (result.hasException) {
        print(result.exception.toString());
        return null;
      }
      var response = result.data.data;
      final map = response as Map<String, dynamic>;
      Data mappedResult = Data.fromJson(map);
      return mappedResult;
    } catch (e) {
      print(e);
      return null;
    }
  }
}

The class name is ApiService, and it creates a Graphql client using the clientToQuery method in the GraphQLConfiguration class. Gql is used to parse GraphQL query strings into the standard GraphQL AST. The response returned is a map and your model is mapped from it.

UI FOLDER

Lastly, we can get to work on our UI, as most of the work is out of the way. I use a future provider to call the endpoint to the UI.

import 'package:flutter/material.dart';
import 'Models/continents_model.dart';
import 'Services/continent_service.dart';
import 'UI/home.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        FutureProvider<Data>(
          create: (_) {
            return ApiService().getContinents();
          },
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        debugShowCheckedModeBanner: false,
        home: HomeView(),
      ),
    );
  }
}

The other views include home.dart where the continents in the world are displayed and countries.dart where countries under each continent are displayed. You can find their files here.

And that’s the end! we have a working app that should look like this.

ezgif.com-gif-maker.gif

If your app doesn’t look the same, don’t forget to check out the Github repository for the project files to see where you might have gone wrong.

Thank you for taking your time to read it, please feel free to leave comments/questions if any.