面向多年 iOS 开发者的零阻力上手
你在 iOS 项目中也许习惯了 URLSession、Alamofire 或 Moya。
换到 Flutter 后,等价的「组合拳」就是 Dio + Retrofit。
本文将带你一次吃透两套库的安装、核心 API、进阶技巧与最佳实践。
特性 | 作用 | iOS 类比 |
---|---|---|
BaseOptions |
全局配置(超时、基址等) | URLSessionConfiguration |
Interceptors | 请求/响应拦截、重试、日志 | URLProtocol / RequestAdapter |
CancelToken |
任务取消 | URLSessionTask.cancel() |
FormData |
表单/文件上传 | multipart/form-data |
download() |
断点续传 | downloadTask(withResumeData:) |
dependencies:
dio: ^5.4.0 # 以实际最新版为准
flutter pub get
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': '[email protected]', 'pwd': '123456'},
);
提示:默认 JSON ⇆
Map
,无需手写解析。
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); // 继续抛出
},
),
);
final cancel = CancelToken();
dio.download(
url,
savePath,
cancelToken: cancel,
onReceiveProgress: (recv, total) =>
debugPrint('Progress ${(recv / total * 100).toStringAsFixed(0)}%'),
);
// …在需要时
cancel.cancel('用户离开页面,停止下载');
与 Android 同名库思路一致:用注解声明接口 ➜ 自动车生成实现 ➜ 调用即得强类型数据。
dependencies:
retrofit: ^4.1.0
dio: ^5.4.0
json_annotation: ^4.9.0
dev_dependencies:
build_runner: ^2.4.10
retrofit_generator: ^8.1.0
json_serializable: ^6.8.0
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,
);
}
flutter pub run build_runner build -d
自动产出的 _UserService
文件包含所有实际的 Dio
调用与 JSON → 模型的序列化逻辑;你只和 接口 打交道。
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('[email protected]', '123456'));
await secureStorage.write(key: 'token', value: token.value);
复用同一 Dio 实例
统一拦截器/超时/证书校验,防止重复配置。
自动刷新 Token
在 Dio 拦截器里检测 401,完成刷新后 handler.resolve(...)
重放失败请求。
环境切换
通过注入 baseUrl
(UserService(dio, baseUrl: kDebug ? dev : prod)
)即可。
响应泛型包装
自定义 BaseResponse
,配合 json_serializable
解析:
class BaseResponse<T> {
final int code;
final String msg;
final T data;
// …fromJson / toJson 省略
}
概念 | 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 | 轻松写单元测试 |
HttpClientAdapter
自定义证书校验
dio.httpClientAdapter = IOHttpClientAdapter()
..onHttpClientCreate = (client) {
client.badCertificateCallback = (_, __, ___) => true; // 仅示例
return client;
};
并发请求:使用 Future.wait([...])
或 Isolate
,避免阻塞 UI。
队列重试:配合 retry
包或自定义拦截器实现指数退避。
缓存:dio_cache_interceptor
支持磁盘和内存双缓存策略。
WebSocket:Dio 不负责,使用 web_socket_channel
。
Dio + Retrofit 为 Flutter 带来了与 iOS 熟悉的 网络层“三件套”:
只要把握「配置统一 → 模型生成 → 拦截链驱动」三步,就能迅速复制在 iOS 积累的工程经验,构建健壮、可测试、易维护的 Flutter 网络栈。
下一步:尝试将现有 Swift 服务层迁移为 Dart 接口,体验全端一致的开发流畅感吧!