mcpField
F
flutter-dio

flutter-dio

github.com/dhruvanbhalara开发30344 次安装8 周前更新
代码仓库

关于 flutter-dio

面向 Flutter 开发的 HTTP 网络技能,介绍使用 Dio 处理类型安全模型、拦截器、重试、缓存和令牌安全,也说明简单请求何时可用 http 包。

主要功能

  1. 01Dio 请求与响应模式
  2. 02类型安全的 JSON 模型
  3. 03身份验证与错误拦截器
  4. 04重试、超时和缓存指南
  5. 05安全存储令牌
  6. 06简单 API 的 http 包用法

适用场景

  1. 01构建生产环境的 Flutter API 客户端
  2. 02附加令牌并处理 401 刷新
  3. 03分类处理网络与服务器错误
  4. 04通过注入的 http.Client 测试请求

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dhruvanbhalara/skills --skill flutter-dio

安装后在 Claude Code 中输入/flutter-dio确认已加载。

详细介绍

使用 Dio 进行网络通信

  • 将 Dio 用作主要的 HTTP 客户端包。
  • 所有请求和响应正文都使用类型安全的模型类,并提供 fromJson / toJson 工厂。
  • 使用带类型的异常妥善处理所有 HTTP 状态码(例如,ServerException、NetworkException、UnauthorizedException)。
  • 设置适当的请求超时时间(connectTimeout、receiveTimeout、sendTimeout)。

Dio 拦截器

  • 使用拦截器处理横切关注点:
    • 身份验证拦截器:将访问令牌附加到请求头,并在收到 401 时处理令牌刷新。
    • 日志记录拦截器:在调试模式下通过 AppLogger 记录请求和响应。
    • 错误拦截器:将 DioException 转换为特定于领域的 Failure 类型。
  • 通过 injectable 集中注册拦截器,确保所有 API 调用的行为一致。

仓储模式

  • DataSources 仅包含原始 Dio API 调用:不包含业务逻辑或映射。
  • 对于网络数据,Repositories 负责协调远程 DataSources 与本地缓存。

重试与弹性

  • 针对暂时性故障(例如,500 错误、超时)实现带指数退避的重试逻辑。
  • 设置最大重试次数(默认:3 次)。
  • 在适当情况下缓存响应,以减少网络调用并改善离线体验。

性能

  • 对大型响应(> 1 MB),使用 compute() 在后台 isolate 中解析 JSON。
  • 不要使用同步网络操作阻塞 UI 线程。

安全

  • 使用 flutter_secure_storage 存储令牌:切勿将其存放在源代码或 SharedPreferences 中。
  • 所有 API 通信都必须使用 HTTPS。

替代方案:http 包

对于不需要拦截器、缓存或重试逻辑的简单 REST 调用,请使用 http 而非 Dio。

Dio 与 http 对比

标准httpDio
拦截器不支持支持完整拦截器链
重试逻辑手动处理内置并支持退避
响应缓存手动处理提供插件
FormData / Multipart手动处理内置
取消请求不支持支持 CancelToken
依赖项最少(1 个包)较重
使用场景简单的 CRUD API生产环境 API 客户端

原型和简单的获取并显示场景使用 http。对于需要身份验证、重试和缓存的生产环境 API 客户端,使用 Dio。

http 基本模式

import 'dart:convert';
import 'package:http/http.dart' as http;

// GET request
Future<Map<String, dynamic>> fetchData(http.Client client) async {
  final response = await client.get(
    Uri.parse('https://api.example.com/data'),
    headers: {'Accept': 'application/json'},
  );

  if (response.statusCode == 200) {
    return jsonDecode(response.body) as Map<String, dynamic>;
  } else {
    throw Exception('Failed to fetch: ${response.statusCode}');
  }
}

// POST request
Future<void> createItem(http.Client client, Map<String, dynamic> body) async {
  final response = await client.post(
    Uri.parse('https://api.example.com/items'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode(body),
  );

  if (response.statusCode != 201) {
    throw Exception('Failed to create: ${response.statusCode}');
  }
}

测试:始终将 http.Client 作为参数传入(而不是直接调用 http.get()),以便在测试中注入模拟对象。

评论

支持 Markdown