loading...
SoluteLabs

Exploring GraphQL with Flutter

milindmevada profile image Milind Mevada ・3 min read

In this Blog post, Let's discuss Various way available to implement GraphQL with Flutter

First of all, What's this GraphQL?

We are not going in depth about the concept of GraphQL in the post, but here is the short description from an official document

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, 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.

GraphQL is developed and now open sourced by the tech team of Facebook, which is a different way to implement APIs in your application. Let's see how we implement this with Flutter

How I will manage this on Flutter?

While you can use normal HTTP GET request to execute Graph Query, Flutter has some cool pubs available which manage this stuffs and make developer's job easy.

If you look for GraphQL client for Flutter, there are good options available like graphql_flutter.

graphql_flutter pub provides a Widget level implementation for Graph Query.
For Example:

Query(
  options: QueryOptions(
    document: readRepositories, // this is a Graph Query
    variables: {
      'nRepositories': 50,
    },
    pollInterval: 10,
  ),
  builder: (QueryResult result, { VoidCallback refetch }) {
    if (result.errors != null) {
      return Text(result.errors.toString());
    }

    if (result.loading) {
      return Text('Loading');
    }

    // it can be either Map or List
    List repositories = result.data['viewer']['repositories']['nodes'];

    return ListView.builder(
      itemCount: repositories.length,
      itemBuilder: (context, index) {
        final repository = repositories[index];

        return Text(repository['name']);
    });
  },
);

This is a very high-level widget implementation which will manage the networking from Widget itself.

But, How I will separate the Network layer in my App? 🤷

Yes!, This is what we also questioned. As we are using BLoC architecture in one of our Flutter application, this implementation was surely not granular to suits.

To answer this question, We analyzed the internal implementation of this pub. Here is the outcome.

Implement GraphQL on BLoC way

Here is a nice pub available graphql_client. This is the same pub which has been used underlying by graphql_flutter. By this, we should be able to separate a network layer in App

Let us take an example of Github Graph API

Let's dive into the code directly

  • Step 1: Basic Setup
//Provide a Base URL
final HttpLink _httpLink = HttpLink(
  uri: 'https://api.github.com/graphql',
);

//Provide authentication, this will go as a Header in Request
final AuthLink _authLink = AuthLink(
  getToken: () async => 'Bearer $GITHUB_TOKEN',
);

final Link _link = _authLink.concat(_httpLink as Link);

GraphQLClient _client;

// Create a common client for further requests
GraphQLClient getGraphQLClient() {
  _client ??= GraphQLClient(
    link: _link,
    cache: InMemoryCache(storageProvider: () {
      return getTemporaryDirectory(); // Provide a cache mechanism
    }),
  );

  return _client;
}
  • Step 2: Repository Layer
class GitHubRepoProvider {
// method will give us Data model
  Future<List<GithubRepo>> getCurrentUserRepos() {
    return getGraphQLClient().query(_queryOptions()).then(_toGitHubRepo);
  }

// provides Graph Query options, we can provide the optional variable here
  QueryOptions _queryOptions() {
    return QueryOptions(
      document: readRepositories,
      variables: <String, dynamic>{
        'nRepositories': 50,
      },
    );
  }

// parse JSON to Data model
  List<GithubRepo> _toGitHubRepo(QueryResult queryResult) {
    if (queryResult.hasErrors) {
      throw Exception();
    }

    final list =
        queryResult.data['viewer']['repositories']['nodes'] as List<dynamic>;

    return list
        .map((repoJson) => GithubRepo.fromJson(repoJson))
        .toList(growable: false);
  }
}

// Graph Query to get repository of current user
const String _readRepositories = r'''
  query ReadRepositories($nRepositories: Int!) {
    viewer {
      repositories(last: $nRepositories) {
        nodes {
          name
          createdAt
          forkCount
        }
      }
    }
  }
''';

Bingo 👍. We now have a Data model. Covert your DataModel into ViewModel from the BLoC 😉

You can see the full working demo Application here 👇. (Don't forget to edit config.dart file to add your Github API token)

GitHub logo milind-mevada-stl / Flutter-GraphQL-Demo

This Project shows demo of GraphQL implementation in Flutter

Flutter GraphQL Demo Build Status

This application shows demo of GraphQL implementation in Flutter using GraphQL Client. Checkout more on our blog post here.

Getting Started

Clone and edit config.dart file, Add your personalized Github API token to get started.

Provide your ideas/suggestions in the comment section or hit me a tweet 👉

Posted on by:

milindmevada profile

Milind Mevada

@milindmevada

Mobile Software Engineer. Focused on Flutter and Native Android development.

SoluteLabs

SoluteLabs is a high-performance team of 25 focused on mobile and web design and development

Discussion

markdown guide
 

@solutelabs Thanks for the nice article. Please let us know how to do graphql subscription with BLoc Pattern