Flutter dio
Skill almasumdev/awesome-flutter-agent-skills/.github/skills/concurrency_and_networking/flutter-dio
Curated agent skills, conventions, and workflows for building Flutter apps with AI coding agents.
npx -y skills add almasumdev/awesome-flutter-agent-skills --skill flutter-dioAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Guidance on Dio HTTP client in Flutter — configuration, interceptors, error handling, retries, and testing. Use this when implementing or debugging networking code.
SKILL.md
3.9 KB, as published. Nobody here has run it
Dio Networking in Flutter
Instructions
Use Dio as the HTTP client for its interceptors, timeouts, cancel tokens, and request/response transformers. Wrap it behind typed API classes — never call Dio directly from widgets.
1. Base Configuration
Register a single Dio instance per environment in DI:
final dioProvider = Provider<Dio>((ref) {
final dio = Dio(BaseOptions(
baseUrl: Env.apiBaseUrl,
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 20),
headers: {'Accept': 'application/json'},
));
dio.interceptors.addAll([
AuthInterceptor(ref),
LogInterceptor(requestBody: kDebugMode, responseBody: kDebugMode),
RetryInterceptor(dio: dio, retries: 2),
]);
return dio;
});
2. Typed API Clients
Either hand-write a class per resource, or use retrofit + build_runner for code-gen:
@RestApi()
abstract class ArticleApi {
factory ArticleApi(Dio dio, {String? baseUrl}) = _ArticleApi;
@GET('/articles')
Future<List<ArticleDto>> fetchArticles({@Query('page') int page = 1});
@GET('/articles/{id}')
Future<ArticleDto> fetchArticle(@Path('id') String id);
}
3. Authentication Interceptor
class AuthInterceptor extends Interceptor {
AuthInterceptor(this.ref);
final Ref ref;
@override
Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
final token = ref.read(authProvider).token;
if (token != null) options.headers['Authorization'] = 'Bearer $token';
handler.next(options);
}
@override
Future<void> onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401) {
final refreshed = await ref.read(authProvider.notifier).refresh();
if (refreshed) {
final clone = await ref.read(dioProvider).fetch(err.requestOptions);
return handler.resolve(clone);
}
}
handler.next(err);
}
}
4. Error Mapping
Convert DioException to domain exceptions at the repository boundary. Never let DioException leak into the UI.
try {
return await _api.fetchArticles();
} on DioException catch (e) {
throw switch (e.type) {
DioExceptionType.connectionTimeout ||
DioExceptionType.receiveTimeout => const NetworkTimeoutException(),
DioExceptionType.badResponse => ServerException(e.response?.statusCode ?? 0),
DioExceptionType.cancel => const RequestCancelled(),
_ => NetworkException(e.message ?? 'Unknown'),
};
}
5. Cancellation
Pass a CancelToken from the caller; cancel on screen dispose or when a newer request supersedes the old one.
final cancel = CancelToken();
final future = api.search(q, cancelToken: cancel);
// later:
cancel.cancel('superseded');
6. Retries and Caching
- Use
dio_smart_retry(or a customRetryInterceptor) for transient 5xx / network errors with exponential backoff. - For caching, use
dio_cache_interceptorwith an explicit policy per endpoint — do not cache POSTs by default.
7. Testing
- Mock
Diowithhttp_mock_adapter(preferred) or inject a fake implementation. - Assert both happy path and error mapping in repository tests.
8. Security
- Never log full request/response bodies in release builds.
- Strip auth headers from logs (
LogInterceptordefault does not). - Use certificate pinning on the platform side for high-sensitivity APIs.
- Store tokens in
flutter_secure_storage, notshared_preferences.
9. Checklist
- Single configured
Dioinstance injected via DI. - Typed API classes, no raw
dio.getfrom widgets or blocs. -
DioExceptionis caught at the repository and mapped to domain errors. - Sensitive data is not logged.
- Requests honor cancellation.