GraphQL has emerged as a powerful alternative to REST APIs, offering a more efficient and flexible way to fetch and manipulate data. For Flutter developers, integrating GraphQL into your apps can significantly enhance data fetching capabilities and improve overall performance. The graphql_flutter
package provides a robust and straightforward way to integrate GraphQL into Flutter applications. This blog post will guide you through using the graphql_flutter
package to seamlessly integrate GraphQL into your Flutter app.
What is GraphQL?
GraphQL is a query language for your API and a server-side runtime for executing those queries. Unlike REST, which fetches a fixed set of data for each endpoint, GraphQL allows clients to request specific data, resulting in more efficient data transfer and reduced over-fetching. Key benefits of GraphQL include:
- Efficient Data Fetching: Clients request only the data they need.
- Reduced Over-Fetching: No unnecessary data is transferred.
- Strongly Typed Schema: Ensures type safety and helps with debugging.
- Introspection: Allows clients to explore the API’s capabilities.
Why Use graphql_flutter
in Flutter?
The graphql_flutter
package is designed to simplify the integration of GraphQL APIs into Flutter applications. It offers several advantages:
- Easy Integration: Simple setup and intuitive API for GraphQL operations.
- Caching Support: Built-in caching to improve performance and reduce network requests.
- UI Components: Pre-built widgets for displaying data and handling loading/error states.
- Subscription Support: Real-time data updates with GraphQL subscriptions.
How to Integrate GraphQL into Your Flutter App Using graphql_flutter
To start integrating GraphQL into your Flutter app, follow these steps:
Step 1: Add the graphql_flutter
Dependency
First, add the graphql_flutter
package to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
graphql_flutter: ^5.1.2
Run flutter pub get
in your terminal to install the package.
Step 2: Set Up the GraphQL Client
Initialize the GraphQL client with the endpoint URL and necessary configurations. Create a file named graphql_client.dart
:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
final HttpLink httpLink = HttpLink(
'https://rickandmortyapi.graphcdn.app/', // Replace with your GraphQL endpoint
);
ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
link: httpLink,
cache: GraphQLCache(store: HiveStore()),
),
);
class GraphQLProvider extends StatelessWidget {
GraphQLProvider({required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
return GraphQLProvider(client: client, child: child);
}
}
In this code:
HttpLink
defines the GraphQL endpoint.GraphQLCache
configures caching usingHiveStore
.GraphQLClient
creates a client instance with the specified link and cache.- The
GraphQLProvider
wraps your app to make the GraphQL client available throughout your widget tree.
Step 3: Wrap Your App with GraphQLProvider
Wrap your main app widget with the GraphQLProvider
in main.dart
:
import 'package:flutter/material.dart';
import 'graphql_client.dart';
import 'home_page.dart'; // Create this file in Step 4
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GraphQL Flutter App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: GraphQLProvider(child: HomePage()),
);
}
}
Step 4: Create a Widget to Query Data
Create a new file named home_page.dart
to fetch and display data using GraphQL queries:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final String query = """
query GetCharacters {
characters {
results {
id
name
}
}
}
""";
return Scaffold(
appBar: AppBar(
title: Text('GraphQL Characters'),
),
body: Query(
options: QueryOptions(
document: gql(query),
),
builder: (QueryResult result, {Refetch? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Center(child: Text("Error: ${result.exception.toString()}"));
}
if (result.isLoading) {
return Center(child: CircularProgressIndicator());
}
List? characters = result.data?['characters']['results'];
if (characters == null) {
return Center(child: Text('No data available'));
}
return ListView.builder(
itemCount: characters.length,
itemBuilder: (context, index) {
final character = characters[index];
return ListTile(
leading: CircleAvatar(
child: Text(character['id'].toString()),
),
title: Text(character['name']),
);
},
);
},
),
);
}
}
In this code:
- The
Query
widget executes the GraphQL query. - The
builder
function handles different states: loading, error, and data. - The data is extracted and displayed in a
ListView
.
Step 5: Run Your Flutter App
Run your Flutter app using flutter run
. You should see a list of characters fetched from the GraphQL API.
Make sure that you have an active internet connection.
Advanced Usage
Caching
The graphql_flutter
package includes a sophisticated caching mechanism that can significantly improve performance. By default, the cache is stored in memory. For persistent storage, use HiveStore
as shown earlier.
Mutations
Mutations are used to modify data on the server. Use the Mutation
widget in a similar way to the Query
widget:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class AddTodoMutation extends StatelessWidget {
@override
Widget build(BuildContext context) {
final String mutation = """
mutation AddTodo(\$title: String!, \$completed: Boolean!) {
addTodo(title: \$title, completed: \$completed) {
id
title
completed
}
}
""";
return Mutation(
options: MutationOptions(
document: gql(mutation),
onCompleted: (dynamic result) {
print("Mutation completed: $result");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Todo Added!')),
);
},
),
builder: (RunMutation runMutation, QueryResult<Object?>? result) {
return ElevatedButton(
onPressed: () {
runMutation({
'title': 'My New Todo',
'completed': false,
});
},
child: Text('Add Todo'),
);
},
);
}
}
Subscriptions
For real-time data updates, use GraphQL subscriptions. Implement a Subscription
widget similar to Query
and Mutation
.
Conclusion
Integrating GraphQL into your Flutter app using the graphql_flutter
package is a straightforward and efficient way to manage data fetching and manipulation. By following the steps outlined in this guide, you can set up a GraphQL client, perform queries, execute mutations, and implement subscriptions, resulting in a more responsive and efficient Flutter application. The package’s robust features, including caching and UI components, make it an excellent choice for modern Flutter development.