Introduction
GraphQL has become a popular choice for API communication in Flutter mobile development. Unlike REST, GraphQL provides a single endpoint with flexible queries, reducing bandwidth and improving performance. In this tutorial, you’ll learn how to integrate a GraphQL API into your Flutter app using the graphql_flutter package. We’ll cover client setup, schema mapping, crafting queries and mutations, response handling with caching, and rendering data in widgets.
Setting Up the GraphQL Client
Start by adding graphql_flutter and gql to your pubspec.yaml. Then wrap your app in a GraphQLProvider and initialize a client with a link and cache. The client link handles HTTP communication, while the cache uses normalized in-memory storage for offline support.
final HttpLink httpLink = HttpLink('https://api.example.com/graphql');
ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
link: httpLink,
cache: GraphQLCache(store: InMemoryStore()),
),
);
void main() => runApp(
GraphQLProvider(
client: client,
child: MyApp(),
),
);Defining Schemas and Models
In GraphQL, you define types on the server, but in Flutter you can create Dart models to map the JSON response. Use code generation or manual parsing with json_serializable. Define classes matching your query fields to ensure type safety and cleaner parsing.
class User {
final String id;
final String name;
User({required this.id, required this.name});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
);
}
}This model maps directly to the server schema’s User type, simplifying serialization.
Writing Queries and Mutations
Use the gql tag to define your operations. Queries fetch data, while mutations modify it. Keep queries concise, selecting only necessary fields.
final String fetchUsers = gql('''
query FetchUsers {
users {
id
name
}
}
''');
final String addUser = gql('''
mutation AddUser($name: String!) {
createUser(input: {name: $name}) {
id
name
}
}
''');Wrap these in Query or Mutation widgets or use the client’s query and mutate methods in your business logic.
Handling Responses and Caching
The graphql_flutter client normalizes and caches responses automatically. Use Query widgets to reactively rebuild on cache updates. Check result.isLoading, result.data, and result.exception to manage UI states. For manual queries:
final QueryResult result = await client.value.query(
QueryOptions(document: fetchUsers),
);
if (result.hasException) {
print(result.exception.toString());
} else {
List usersJson = result.data!['users'];
List<User> users = usersJson.map((u) => User.fromJson(u)).toList();
}Leverage fetchPolicy to control network vs. cache behavior: cacheFirst, networkOnly, or cacheAndNetwork.
Integrating with Widgets
In Flutter, wrap UI elements with Query or Mutation builders. Handle loading and error states in builders, returning spinners or error messages. Once data arrives, map JSON to Dart models and render with standard widgets like ListView.
Query(
options: QueryOptions(document: fetchUsers),
builder: (result, {fetchMore, refetch}) {
if (result.isLoading) return CircularProgressIndicator();
if (result.hasException) return Text('Error');
final users = (result.data!['users'] as List)
.map((u) => User.fromJson(u))
.toList();
return ListView(
children: users.map((u) => Text(u.name)).toList(),
);
},
);This pattern keeps UI and data logic separate and reactive.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Integrating GraphQL in Flutter enhances mobile development by reducing over-fetching and consolidating endpoints. With graphql_flutter, you get built-in caching, query management, and widget integration. By defining Dart models for schema types, crafting precise queries and mutations, handling responses with policies, and rendering data in widgets, you’ll build responsive, efficient apps with a modern API approach. Start experimenting today to see immediate gains in performance and developer experience.