DEV Community

Milind Mevada for SoluteLabs

Posted on

Exploring GraphQL with Flutter

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 👉

Top comments (3)

Collapse
 
thiyaga123 profile image
thiyaga123

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

Collapse
 
vasilich6107 profile image
Vasiliy Ditsyak

You can try this library with generic approach for cooking graphql_flutter + bloc
pub.dev/packages/graphql_flutter_bloc

Collapse
 
cdaiga profile image
Claude Daiga Dohnji

Great content. Please how can one integrate a graphql api that uses cookies to store the authentication token?