Flutter 网络栈入门,Dio 与 Retrofit 全面指南
面向多年 iOS 开发者的零阻力上手
写在前面
你在 iOS 项目中也许习惯了 URLSession、Alamofire 或 Moya。
换到 Flutter 后,等价的「组合拳」就是 Dio + Retrofit。
本文将带你一次吃透两套库的安装、核心 API、进阶技巧与最佳实践。
1. Dio:Flutter 里的「Alamofire」
特性 | 作用 | iOS 类比 |
---|---|---|
BaseOptions | 全局配置(超时、基址等) | URLSessionConfiguration |
Interceptors | 请求/响应拦截、重试、日志 | URLProtocol / RequestAdapter |
CancelToken | 任务取消 | URLSessionTask.cancel() |
FormData | 表单/文件上传 | multipart/form-data |
download() | 断点续传 | downloadTask(withResumeData:) |
1.1 安装
dependencies:dio: ^5.4.0 # 以实际最新版为准
flutter pub get
1.2 基础用法
final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com',connectTimeout: const Duration(seconds: 10),receiveTimeout: const Duration(seconds: 15),headers: {'Accept': 'application/json'},),
);// GET
final res = await dio.get('/users/42');
print(res.data);// POST
await dio.post('/login',data: {'email': 'me@example.com', 'pwd': '123456'},
);
提示:默认 JSON ⇆
Map<String,dynamic>
,无需手写解析。
1.3 拦截器 (Interceptors)
dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {options.headers['Authorization'] = 'Bearer $token';return handler.next(options); // 继续},onError: (e, handler) async {if (e.response?.statusCode == 401) {// 刷新 token 后重试final newToken = await _refreshToken();final request = e.requestOptions;request.headers['Authorization'] = 'Bearer $newToken';return handler.resolve(await dio.fetch(request));}return handler.next(e); // 继续抛出},),
);
1.4 取消 & 进度
final cancel = CancelToken();dio.download(url,savePath,cancelToken: cancel,onReceiveProgress: (recv, total) =>debugPrint('Progress ${(recv / total * 100).toStringAsFixed(0)}%'),
);// …在需要时
cancel.cancel('用户离开页面,停止下载');
2. Retrofit:类型安全的 REST 接口生成器
与 Android 同名库思路一致:用注解声明接口 ➜ 自动车生成实现 ➜ 调用即得强类型数据。
2.1 安装
dependencies:retrofit: ^4.1.0dio: ^5.4.0json_annotation: ^4.9.0dev_dependencies:build_runner: ^2.4.10retrofit_generator: ^8.1.0json_serializable: ^6.8.0
2.2 声明接口(user_service.dart
)
part 'user_service.g.dart'; // 生成文件(baseUrl: 'https://api.example.com')
abstract class UserService {factory UserService(Dio dio, {String baseUrl}) = _UserService;('/users/{id}')Future<User> getUser(() int id);('/login')Future<AuthToken> login(() LoginPayload body);('/search')Future<List<User>> search(('keyword') String q,('X-Trace-Id') String traceId,);
}
2.3 生成代码
flutter pub run build_runner build -d
自动产出的 _UserService
文件包含所有实际的 Dio
调用与 JSON → 模型的序列化逻辑;你只和 接口 打交道。
2.4 调用
final dio = Dio()..interceptors.add(LogInterceptor());
final api = UserService(dio);final user = await api.getUser(42);
debugPrint(user.name);final token = await api.login(LoginPayload('me@example.com', '123456'));
await secureStorage.write(key: 'token', value: token.value);
3. Dio × Retrofit:组合最佳实践
-
复用同一 Dio 实例
统一拦截器/超时/证书校验,防止重复配置。 -
自动刷新 Token
在 Dio 拦截器里检测 401,完成刷新后handler.resolve(...)
重放失败请求。 -
环境切换
通过注入baseUrl
(UserService(dio, baseUrl: kDebug ? dev : prod)
)即可。 -
响应泛型包装
自定义BaseResponse<T>
,配合json_serializable
解析:class BaseResponse<T> {final int code;final String msg;final T data;// …fromJson / toJson 省略 }
4. 与 iOS 思维对照
概念 | Flutter (Dio / Retrofit) | iOS 对应 | 迁移 Tips |
---|---|---|---|
全局配置 | BaseOptions | URLSessionConfiguration | 把常用 Header、超时集中写 |
拦截器链 | InterceptorsWrapper | URLProtocol / RequestInterceptor | 顺序执行,可短路 |
类型安全接口 | @GET , @POST 注解 | Moya TargetType / Swift Protocol | Dart 代码生成替代手写 |
取消任务 | CancelToken | URLSessionTask | 页面销毁就 cancel |
Mock 数据 | MockAdapter | OHHTTPStubs / Mocker | 轻松写单元测试 |
5. 常见坑 & 进阶技巧
-
HttpClientAdapter
自定义证书校验dio.httpClientAdapter = IOHttpClientAdapter()..onHttpClientCreate = (client) {client.badCertificateCallback = (_, __, ___) => true; // 仅示例return client;};
-
并发请求:使用
Future.wait([...])
或Isolate
,避免阻塞 UI。 -
队列重试:配合
retry
包或自定义拦截器实现指数退避。 -
缓存:
dio_cache_interceptor
支持磁盘和内存双缓存策略。 -
WebSocket:Dio 不负责,使用
web_socket_channel
。
6. 结语
Dio + Retrofit 为 Flutter 带来了与 iOS 熟悉的 网络层“三件套”:
- 强大且可插拔的 HTTP 客户端
- 类型安全、零样板的接口定义
- 完善的拦截/重试/监控生态
只要把握「配置统一 → 模型生成 → 拦截链驱动」三步,就能迅速复制在 iOS 积累的工程经验,构建健壮、可测试、易维护的 Flutter 网络栈。
下一步:尝试将现有 Swift 服务层迁移为 Dart 接口,体验全端一致的开发流畅感吧!