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)
milind-mevada-stl / Flutter-GraphQL-Demo
This Project shows demo of GraphQL implementation in Flutter
Flutter GraphQL Demo
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 👉
Exploring #GraphQL on #Flutter. Using GraphQL client pub.
Here is a sample demo application github.com/milind-mevada-…
Thanks @SmitSonani for quick code review.
@FlutterDev @FlutterAHM @FlutterComm @r_FlutterDev @FlutterWk @dart_lang @prasadsunny109:50 AM - 30 May 2019
Top comments (3)
@solutelabs Thanks for the nice article. Please let us know how to do graphql subscription with BLoc Pattern
You can try this library with generic approach for cooking graphql_flutter + bloc
pub.dev/packages/graphql_flutter_bloc
Great content. Please how can one integrate a graphql api that uses cookies to store the authentication token?