Master HTTP clients, REST APIs, GraphQL integration, WebSockets, and JSON serialization in Flutter applications. Use when implementing API calls, handling network requests, parsing JSON, or working with real-time data.
From flutter-corenpx claudepluginhub aaronbassett/agent-foundry --plugin flutter-coreThis skill uses the workspace's default tool permissions.
examples/api-client.mdexamples/offline-sync.mdreferences/error-handling.mdreferences/graphql-integration.mdreferences/http-client.mdreferences/json-serialization.mdreferences/rest-api.mdreferences/websockets.mdSearches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides implementation of event-driven hooks in Claude Code plugins using prompt-based validation and bash commands for PreToolUse, Stop, and session events.
Master HTTP clients, REST APIs, GraphQL, WebSockets, and JSON serialization in Flutter applications.
Use this skill when working with Flutter applications that need to:
Networking is fundamental to modern Flutter applications. Whether you're fetching data from a REST API, subscribing to real-time updates via WebSockets, or querying a GraphQL backend, Flutter provides powerful tools and packages to handle all networking scenarios efficiently and reliably.
This skill covers the complete spectrum of networking in Flutter, from basic HTTP requests to advanced patterns like offline-first architecture, request interceptors, and automatic retry strategies. You'll learn to choose the right networking solution for your needs and implement it following industry best practices.
Flutter offers multiple HTTP client options, each suited to different use cases:
The official http package is Flutter's simplest HTTP client, ideal for straightforward API calls. It provides basic GET, POST, PUT, DELETE methods with minimal configuration. Use it for simple applications or when you need a lightweight solution without advanced features.
The package is cross-platform, supporting Android, iOS, macOS, Windows, Linux, and web. However, it requires platform-specific permissions configuration, such as internet permission in AndroidManifest.xml for Android and network client entitlements for macOS.
Dio is a powerful, feature-rich HTTP client that has become the industry standard for Flutter networking. It excels with:
Dio's interceptor system is particularly powerful, allowing you to implement cross-cutting concerns like JWT authentication, request logging, error handling, and response caching without duplicating code across your application.
For production applications, Dio is typically the better choice due to its robust feature set and excellent error handling. Use the basic http package only for simple apps or quick prototypes. For enterprise applications requiring advanced features like certificate pinning, custom adapters, or sophisticated retry logic, Dio provides the necessary flexibility.
REST (Representational State Transfer) APIs are the most common backend architecture for Flutter applications. Implementing REST APIs effectively requires understanding HTTP methods, status codes, headers, and error handling.
REST APIs typically expose four core operations (CRUD):
Each operation should be wrapped in a service or repository class that handles serialization, error handling, and business logic. This separation of concerns makes your code more testable and maintainable.
Most production APIs require authentication, typically implemented using:
Dio interceptors are ideal for implementing authentication, automatically adding authentication headers to every request and handling token refresh when tokens expire.
Robust error handling distinguishes production-quality apps from prototypes. Your networking layer should handle:
Implement a consistent error handling strategy using custom exception types and a centralized error handler that can display appropriate messages to users.
GraphQL is an alternative to REST that allows clients to request exactly the data they need, reducing over-fetching and under-fetching. The graphql_flutter package provides comprehensive GraphQL support for Flutter.
GraphQL operates through three operation types:
Unlike REST, GraphQL uses a single endpoint and a typed schema that defines available operations and data structures. This schema provides excellent type safety and enables powerful tooling.
The package provides three primary widgets:
All widgets must be wrapped in a GraphQLProvider that configures the GraphQL client, including the endpoint URL, authentication, and caching policies.
graphql_flutter includes a sophisticated caching system that normalizes data by type and ID. This enables:
Proper cache configuration significantly improves perceived performance and enables offline functionality.
WebSockets provide full-duplex communication channels over a single TCP connection, enabling real-time bidirectional data flow. They're essential for features like chat, live notifications, collaborative editing, and real-time dashboards.
Flutter's web_socket_channel package provides a Stream-based API for WebSocket communication. The package abstracts platform differences and provides a consistent interface across all Flutter platforms.
WebSocket connections follow a lifecycle:
WebSockets integrate naturally with Flutter's reactive architecture through Streams. Use StreamBuilder widgets to display real-time data, and StreamControllers to manage WebSocket state in your business logic layer.
Production WebSocket implementations must handle:
Implement a WebSocket manager class that handles these concerns automatically, exposing a simple Stream interface to your application code.
JSON is the standard data format for web APIs. Flutter provides multiple approaches to JSON serialization, from manual parsing to automatic code generation.
For simple data structures, manual serialization using dart:convert is straightforward. You write fromJson and toJson methods manually. This approach works for small projects but becomes error-prone and tedious as your data models grow.
The json_serializable package automatically generates serialization code from annotated classes. This approach:
To use json_serializable, annotate your model classes with @JsonSerializable() and run build_runner to generate the serialization code.
Freezed combines code generation with immutable data classes, providing:
Freezed is the recommended approach for production applications, especially when combined with state management solutions like Riverpod or Bloc. The immutability guarantees eliminate entire classes of bugs related to unexpected state mutations.
For complex data types (DateTime, enums, nested objects), implement custom JsonConverter classes. These converters handle special serialization logic and can be reused across your application.
Robust error handling is critical for production applications. Network operations can fail in numerous ways, and your application must handle failures gracefully.
Categorize network errors into distinct types:
Create custom exception classes for each category, including relevant context like status codes, error messages, and original exceptions.
Many network failures are transient and succeed when retried. Implement retry logic with:
Dio's interceptor system makes implementing retry logic straightforward. For selective retries, only retry on network errors and 5xx server errors, never on 4xx client errors which indicate problems with the request itself.
Modern applications should function partially or fully while offline. Implement offline support through:
The repository pattern provides an excellent abstraction for offline handling, presenting a unified data interface regardless of connectivity state.
Offline-first applications prioritize local data and synchronize with servers opportunistically. This architecture improves perceived performance and enables true offline functionality.
The repository pattern is central to offline-first architecture. Repositories:
A typical repository combines a local database (SQLite, Hive, Isar) with a remote API client, returning local data immediately and updating from the server in the background.
Implement synchronization using:
Conflicts occur when data is modified both locally and remotely before synchronization. Common resolution strategies include:
Choose a strategy based on your application's requirements. Last write wins works for most applications, while user resolution is necessary for collaborative editing.
Follow these best practices for production-quality networking code:
For detailed implementation guidance, see:
Complete, production-ready examples:
dependencies:
dio: ^5.4.0
graphql_flutter: ^5.1.0
web_socket_channel: ^2.4.0
json_annotation: ^4.8.1
freezed_annotation: ^2.4.1
dev_dependencies:
build_runner: ^2.4.7
json_serializable: ^6.7.1
freezed: ^2.4.6
final dio = Dio();
final response = await dio.get('https://api.example.com/users');
final users = (response.data as List)
.map((json) => User.fromJson(json))
.toList();
Query(
options: QueryOptions(
document: gql('''
query GetUser(\$id: ID!) {
user(id: \$id) { id name email }
}
'''),
variables: {'id': userId},
),
builder: (result, {fetchMore, refetch}) {
if (result.isLoading) return CircularProgressIndicator();
if (result.hasException) return Text('Error: ${result.exception}');
return UserWidget(user: result.data['user']);
},
)
final channel = WebSocketChannel.connect(
Uri.parse('wss://api.example.com/ws'),
);
// Listen to messages
channel.stream.listen((message) {
print('Received: $message');
});
// Send messages
channel.sink.add('Hello, server!');
@freezed
class User with _$User {
const factory User({
required String id,
required String name,
required String email,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) =>
_$UserFromJson(json);
}
Mastering networking in Flutter requires understanding multiple technologies: HTTP clients, REST APIs, GraphQL, WebSockets, and JSON serialization. Each serves specific use cases, and production applications typically combine several approaches.
Start with Dio for HTTP requests, implement proper error handling and retry logic, and add offline support through the repository pattern. Use code generation for JSON serialization to eliminate boilerplate and prevent runtime errors. For real-time features, integrate WebSockets or GraphQL subscriptions.
Following the patterns and practices outlined in this skill will help you build robust, performant, and user-friendly Flutter applications that handle networking gracefully under all conditions.