网络请求
Flutter 应用经常需要与后端 API 交互。本章介绍两种网络请求方案:基础的 http 包和功能更强大的 dio 包。
http — 基础网络请求
http 是 Dart 官方提供的 HTTP 客户端,简单易用。
安装
bash
flutter pub add httpGET 请求
dart
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> fetchUsers() async {
final response = await http.get(Uri.parse('https://api.example.com/users'));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
// 解析 JSON
} else {
throw Exception('请求失败: ${response.statusCode}');
}
}POST 请求
dart
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> createUser() async {
final response = await http.post(
Uri.parse('https://api.example.com/users'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'name': '张三', 'age': 25}),
);
}常用方法
| 方法 | 说明 |
|---|---|
http.get() | GET 请求 |
http.post() | POST 请求 |
http.put() | PUT 请求 |
http.patch() | PATCH 请求 |
http.delete() | DELETE 请求 |
dio — 功能强大的网络请求
dio 是 Flutter 社区最流行的 HTTP 客户端,支持拦截器、取消请求、文件上传下载、超时重试等功能。
安装
bash
flutter pub add dio基本用法
dart
import 'package:dio/dio.dart';
final dio = Dio();
// GET 请求
final response = await dio.get(
'https://api.example.com/users',
queryParameters: {'page': 1, 'size': 20},
);
// POST 请求
final response = await dio.post(
'https://api.example.com/users',
data: {'name': '张三', 'age': 25},
);
// 获取响应数据
final data = response.data; // 自动解析(根据 responseType)
final statusCode = response.statusCode;
final headers = response.headers;BaseOptions — 全局配置
dart
final dio = Dio(BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: Duration(seconds: 10),
receiveTimeout: Duration(seconds: 10),
sendTimeout: Duration(seconds: 10),
headers: {
'Content-Type': 'application/json',
},
));拦截器
拦截器可以在请求前/后统一处理,如添加 Token、处理错误等:
dart
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
// 请求前:添加 Token
final token = StorageService.getToken();
if (token != null) {
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options); // 继续请求
},
onResponse: (response, handler) {
// 响应后:统一处理
handler.next(response);
},
onError: (error, handler) {
// 错误处理
if (error.response?.statusCode == 401) {
// Token 过期,跳转登录
}
handler.next(error);
},
));日志拦截器
dart
dio.interceptors.add(LogInterceptor(
requestBody: true,
responseBody: true,
));取消请求
dart
final cancelToken = CancelToken();
// 发起请求时传入
dio.get('/users', cancelToken: cancelToken);
// 取消请求
cancelToken.cancel('用户取消了请求');文件下载
dart
await dio.download(
'https://example.com/file.pdf',
'/path/to/save/file.pdf',
onReceiveProgress: (received, total) {
if (total != -1) {
print('下载进度: ${(received / total * 100).toStringAsFixed(0)}%');
}
},
);文件上传
dart
final formData = FormData.fromMap({
'name': '张三',
'file': await MultipartFile.fromFile(
'/path/to/file.jpg',
filename: 'photo.jpg',
),
});
final response = await dio.post('/upload', data: formData);超时与重试
dart
try {
final response = await dio.get('/users');
} on DioException catch (e) {
switch (e.type) {
case DioExceptionType.connectionTimeout:
print('连接超时');
break;
case DioExceptionType.sendTimeout:
print('发送超时');
break;
case DioExceptionType.receiveTimeout:
print('接收超时');
break;
case DioExceptionType.connectionError:
print('网络连接失败');
break;
default:
print('其他错误: ${e.message}');
}
}封装 Dio 单例
dart
class HttpService {
static final HttpService _instance = HttpService._();
factory HttpService() => _instance;
HttpService._();
late final Dio _dio;
void init() {
_dio = Dio(BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: Duration(seconds: 10),
receiveTimeout: Duration(seconds: 10),
));
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
final token = StorageService.getToken();
if (token != null) {
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options);
},
onError: (error, handler) async {
if (error.response?.statusCode == 401) {
// Token 过期处理
}
handler.next(error);
},
));
}
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);
}
}http vs dio 选择
| 特性 | http | dio |
|---|---|---|
| 学习成本 | 低 | 中 |
| 拦截器 | 不支持 | 支持 |
| 取消请求 | 不支持 | 支持 |
| 文件上传下载 | 手动处理 | 内置支持 |
| 超时重试 | 手动处理 | 内置支持 |
| 全局配置 | 不支持 | 支持 |
| 适用 | 简单项目 | 正式项目(推荐) |
