agentsclimarketplace

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.

Install
npx -y skills add almasumdev/awesome-flutter-agent-skills --skill flutter-dio

Assembled 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 custom RetryInterceptor) for transient 5xx / network errors with exponential backoff.
  • For caching, use dio_cache_interceptor with an explicit policy per endpoint — do not cache POSTs by default.

7. Testing

  • Mock Dio with http_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 (LogInterceptor default does not).
  • Use certificate pinning on the platform side for high-sensitivity APIs.
  • Store tokens in flutter_secure_storage, not shared_preferences.

9. Checklist

  • Single configured Dio instance injected via DI.
  • Typed API classes, no raw dio.get from widgets or blocs.
  • DioException is caught at the repository and mapped to domain errors.
  • Sensitive data is not logged.
  • Requests honor cancellation.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.