Flutter Dio 网络请求详解:企业级 HTTP 客户端

引言
在 Flutter 开发中,网络请求是不可或缺的一部分。Dio 是一个强大的 HTTP 客户端库,支持拦截器、全局配置、FormData、文件上传下载等功能,是 Flutter 社区最受欢迎的网络请求库之一。
Dio 基础用法
安装依赖
dependencies:
dio: ^5.0.0
创建 Dio 实例
import 'package:dio/dio.dart';
final dio = Dio();
基本 GET 请求
void fetchData() async {
try {
final response = await dio.get('https://api.example.com/data');
print(response.data);
} catch (e) {
print('Error: $e');
}
}
基本 POST 请求
void postData() async {
try {
final response = await dio.post(
'https://api.example.com/data',
data: {
'name': 'John',
'age': 30,
},
);
print(response.data);
} catch (e) {
print('Error: $e');
}
}
高级配置
全局配置
final dio = Dio(BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 5),
receiveTimeout: const Duration(seconds: 3),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token',
},
));
请求配置
final response = await dio.get(
'/users',
queryParameters: {'page': 1, 'limit': 10},
options: Options(
method: 'GET',
headers: {'Custom-Header': 'value'},
responseType: ResponseType.json,
),
);
拦截器
请求拦截器
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
print('Request: ${options.method} ${options.path}');
options.headers['Authorization'] = 'Bearer token';
return handler.next(options);
},
));
响应拦截器
dio.interceptors.add(InterceptorsWrapper(
onResponse: (response, handler) {
print('Response: ${response.statusCode}');
return handler.next(response);
},
));
错误拦截器
dio.interceptors.add(InterceptorsWrapper(
onError: (DioException e, handler) {
print('Error: ${e.response?.statusCode}');
return handler.next(e);
},
));
重试拦截器
dio.interceptors.add(RetryInterceptor(
dio: dio,
retries: 3,
retryDelay: const Duration(seconds: 1),
));
文件上传与下载
文件上传
void uploadFile() async {
final formData = FormData.fromMap({
'file': await MultipartFile.fromFile(
'/path/to/file.jpg',
filename: 'photo.jpg',
),
'description': 'A beautiful photo',
});
try {
final response = await dio.post(
'/upload',
data: formData,
onSendProgress: (sent, total) {
print('Progress: ${(sent / total * 100).toStringAsFixed(0)}%');
},
);
print(response.data);
} catch (e) {
print('Error: $e');
}
}
文件下载
void downloadFile() async {
try {
final response = await dio.download(
'https://example.com/file.pdf',
'/path/to/save/file.pdf',
onReceiveProgress: (received, total) {
print('Progress: ${(received / total * 100).toStringAsFixed(0)}%');
},
);
print('Download completed');
} catch (e) {
print('Error: $e');
}
}
取消请求
CancelToken cancelToken = CancelToken();
void fetchData() async {
try {
final response = await dio.get(
'/data',
cancelToken: cancelToken,
);
print(response.data);
} catch (e) {
if (e is DioException && e.type == DioExceptionType.cancel) {
print('Request cancelled');
}
}
}
// 取消请求
cancelToken.cancel('Request cancelled by user');
封装最佳实践
创建 API 服务类
class ApiService {
late Dio _dio;
ApiService() {
_dio = Dio(BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 5),
receiveTimeout: const Duration(seconds: 3),
));
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
options.headers['Authorization'] = 'Bearer ${getToken()}';
return handler.next(options);
},
onError: (e, handler) {
if (e.response?.statusCode == 401) {
// 处理未授权
refreshToken();
}
return handler.next(e);
},
));
}
Future<Response> get(String path, {Map<String, dynamic>? queryParameters}) {
return _dio.get(path, queryParameters: queryParameters);
}
Future<Response> post(String path, {dynamic data}) {
return _dio.post(path, data: data);
}
Future<Response> put(String path, {dynamic data}) {
return _dio.put(path, data: data);
}
Future<Response> delete(String path) {
return _dio.delete(path);
}
}
模型转换
class User {
final String id;
final String name;
final String email;
User({required this.id, required this.name, required this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
};
}
}
class UserRepository {
final ApiService apiService;
UserRepository(this.apiService);
Future<User> getUser(String id) async {
final response = await apiService.get('/users/$id');
return User.fromJson(response.data);
}
Future<List<User>> getUsers() async {
final response = await apiService.get('/users');
return (response.data as List).map((json) => User.fromJson(json)).toList();
}
}
错误处理
统一错误处理
class ApiException implements Exception {
final String message;
final int? statusCode;
ApiException({required this.message, this.statusCode});
}
Future<T> safeApiCall<T>(Future<Response> Function() apiCall) async {
try {
final response = await apiCall();
return response.data as T;
} on DioException catch (e) {
throw ApiException(
message: e.message ?? 'Unknown error',
statusCode: e.response?.statusCode,
);
}
}
测试支持
Mock 请求
void main() {
late Dio dio;
late ApiService apiService;
setUp(() {
dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'));
apiService = ApiService();
});
test('get user', () async {
final user = await apiService.getUser('1');
expect(user.id, '1');
});
}
性能优化
请求缓存
dio.interceptors.add(CacheInterceptor());
连接池
final dio = Dio(BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 5),
));
dio.httpClientAdapter = HttpClientAdapter(
ConnectionManager(
idleTimeout: const Duration(seconds: 30),
maxConnections: 10,
),
);
总结
Dio 是一个功能强大的 HTTP 客户端库,提供了丰富的功能和良好的扩展性。通过合理使用拦截器、封装 API 服务和错误处理,我们可以构建健壮的网络请求层。
掌握 Dio 后,你可以:
- 轻松发起各种 HTTP 请求
- 实现请求拦截和响应处理
- 上传和下载文件
- 取消请求
- 构建可测试的网络层
Dio 是 Flutter 网络请求的首选方案,值得深入学习和使用。

2180

被折叠的 条评论
为什么被折叠?



