Flutter网络请求高级技巧
·
Flutter网络请求高级技巧
1. 核心概念
1.1 网络库
- http:Flutter官方推荐的网络库
- dio:功能强大的第三方网络库
- retrofit:基于Dart注解的REST客户端生成器
1.2 请求方法
- GET:获取资源
- POST:创建资源
- PUT:更新资源
- DELETE:删除资源
- PATCH:部分更新资源
1.3 响应处理
- 状态码:HTTP状态码
- 响应体:服务器返回的数据
- 错误处理:网络错误、服务器错误
2. 高级技巧
2.1 基础网络请求
// 使用http库
import 'package:http/http.dart' as http;
Future<void> fetchData() async {
try {
final response = await http.get(Uri.parse('https://api.example.com/data'));
if (response.statusCode == 200) {
// 处理成功响应
print('Response: ${response.body}');
} else {
// 处理错误响应
print('Error: ${response.statusCode}');
}
} catch (e) {
// 处理网络错误
print('Network error: $e');
}
}
// 使用dio库
import 'package:dio/dio.dart';
Future<void> fetchDataWithDio() async {
try {
final dio = Dio();
final response = await dio.get('https://api.example.com/data');
// 处理成功响应
print('Response: ${response.data}');
} catch (e) {
// 处理错误
print('Error: $e');
}
}
2.2 拦截器
// 创建dio实例
final dio = Dio();
// 添加请求拦截器
dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
// 在发送请求之前做一些处理
print('Request: ${options.uri}');
// 添加认证token
options.headers['Authorization'] = 'Bearer your-token';
return handler.next(options);
},
onResponse: (response, handler) {
// 在收到响应后做一些处理
print('Response: ${response.statusCode}');
return handler.next(response);
},
onError: (DioException e, handler) {
// 处理错误
print('Error: ${e.message}');
return handler.next(e);
},
));
// 使用带拦截器的dio实例
Future<void> fetchData() async {
try {
final response = await dio.get('https://api.example.com/data');
print('Response: ${response.data}');
} catch (e) {
print('Error: $e');
}
}
2.3 错误处理
Future<void> fetchData() async {
try {
final dio = Dio();
final response = await dio.get('https://api.example.com/data');
print('Response: ${response.data}');
} on DioException catch (e) {
if (e.response != null) {
// 服务器返回错误状态码
print('Server error: ${e.response?.statusCode}');
print('Error data: ${e.response?.data}');
} else {
// 网络错误
print('Network error: ${e.message}');
}
} catch (e) {
// 其他错误
print('Error: $e');
}
}
// 自定义错误处理类
class ApiError {
final int statusCode;
final String message;
ApiError(this.statusCode, this.message);
factory ApiError.fromDioException(DioException e) {
if (e.response != null) {
return ApiError(
e.response!.statusCode!,
e.response!.data['message'] ?? 'Server error',
);
} else {
return ApiError(0, e.message ?? 'Network error');
}
}
}
Future<void> fetchDataWithCustomError() async {
try {
final dio = Dio();
final response = await dio.get('https://api.example.com/data');
print('Response: ${response.data}');
} on DioException catch (e) {
final error = ApiError.fromDioException(e);
print('Error: ${error.statusCode} - ${error.message}');
}
}
2.4 缓存
// 使用dio的缓存拦截器
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cache_interceptor_hive_store/dio_cache_interceptor_hive_store.dart';
void setupDio() {
// 缓存配置
final cacheOptions = CacheOptions(
store: HiveCacheStore('.cache'),
policy: CachePolicy.request, // 请求时缓存
maxStale: Duration(days: 7), // 缓存最大过期时间
priority: CachePriority.normal,
);
// 创建dio实例
final dio = Dio()..interceptors.add(DioCacheInterceptor(options: cacheOptions));
}
// 手动缓存
class ApiService {
final Dio _dio;
final Map<String, Response> _cache = {};
ApiService(this._dio);
Future<Response> get(String url) async {
// 检查缓存
if (_cache.containsKey(url)) {
return _cache[url]!;
}
// 发起请求
final response = await _dio.get(url);
// 缓存响应
_cache[url] = response;
return response;
}
void clearCache() {
_cache.clear();
}
}
2.5 文件上传和下载
// 文件上传
Future<void> uploadFile() async {
final dio = Dio();
// 单文件上传
final formData = FormData.fromMap({
'name': 'John Doe',
'file': await MultipartFile.fromFile('path/to/file.jpg', filename: 'photo.jpg'),
});
try {
final response = await dio.post('https://api.example.com/upload', data: formData);
print('Upload successful: ${response.data}');
} catch (e) {
print('Upload error: $e');
}
}
// 多文件上传
Future<void> uploadMultipleFiles() async {
final dio = Dio();
final formData = FormData.fromMap({
'name': 'John Doe',
'files': [
await MultipartFile.fromFile('path/to/file1.jpg', filename: 'photo1.jpg'),
await MultipartFile.fromFile('path/to/file2.jpg', filename: 'photo2.jpg'),
],
});
try {
final response = await dio.post('https://api.example.com/upload-multiple', data: formData);
print('Upload successful: ${response.data}');
} catch (e) {
print('Upload error: $e');
}
}
// 文件下载
Future<void> downloadFile() async {
final dio = Dio();
try {
final response = await dio.download(
'https://api.example.com/file',
'path/to/save/file.pdf',
onReceiveProgress: (count, total) {
print('Download progress: ${(count / total * 100).toStringAsFixed(0)}%');
},
);
print('Download successful');
} catch (e) {
print('Download error: $e');
}
}
2.6 网络状态管理
// 检查网络状态
import 'package:connectivity_plus/connectivity_plus.dart';
Future<void> checkNetworkStatus() async {
final connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
print('No internet connection');
} else if (connectivityResult == ConnectivityResult.mobile) {
print('Connected to mobile network');
} else if (connectivityResult == ConnectivityResult.wifi) {
print('Connected to wifi');
}
}
// 监听网络状态变化
void listenToNetworkChanges() {
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if (result == ConnectivityResult.none) {
print('No internet connection');
} else if (result == ConnectivityResult.mobile) {
print('Connected to mobile network');
} else if (result == ConnectivityResult.wifi) {
print('Connected to wifi');
}
});
}
// 网络状态管理服务
class NetworkService {
final Connectivity _connectivity = Connectivity();
Stream<ConnectivityResult> get onNetworkChange => _connectivity.onConnectivityChanged;
Future<bool> isConnected() async {
final result = await _connectivity.checkConnectivity();
return result != ConnectivityResult.none;
}
}
3. 最佳实践
3.1 代码组织
- 服务层:将网络请求封装为服务
- 模型层:定义数据模型
- 存储层:处理缓存和本地存储
- 工具类:提取通用的网络工具函数
3.2 性能优化
- 缓存:合理使用缓存减少网络请求
- 批量请求:合并多个请求减少网络开销
- 压缩:使用gzip压缩减少数据传输量
- 超时设置:合理设置请求超时时间
- 重试机制:实现请求重试逻辑
3.3 安全性
- HTTPS:使用HTTPS协议
- 认证:使用安全的认证方式
- 加密:加密敏感数据
- 防注入:防止SQL注入等攻击
- CORS:正确配置CORS
3.4 可测试性
- 模拟网络请求:使用mock数据进行测试
- 单元测试:测试网络服务的各个部分
- 集成测试:测试网络请求的完整流程
4. 实际应用
4.1 电商应用网络服务
// 产品服务
class ProductService {
final Dio _dio;
ProductService(this._dio);
Future<List<Product>> getProducts() async {
try {
final response = await _dio.get('/products');
final List<dynamic> data = response.data;
return data.map((item) => Product.fromJson(item)).toList();
} catch (e) {
print('Error fetching products: $e');
throw e;
}
}
Future<Product> getProductById(String id) async {
try {
final response = await _dio.get('/products/$id');
return Product.fromJson(response.data);
} catch (e) {
print('Error fetching product: $e');
throw e;
}
}
Future<Product> createProduct(Product product) async {
try {
final response = await _dio.post('/products', data: product.toJson());
return Product.fromJson(response.data);
} catch (e) {
print('Error creating product: $e');
throw e;
}
}
Future<Product> updateProduct(String id, Product product) async {
try {
final response = await _dio.put('/products/$id', data: product.toJson());
return Product.fromJson(response.data);
} catch (e) {
print('Error updating product: $e');
throw e;
}
}
Future<void> deleteProduct(String id) async {
try {
await _dio.delete('/products/$id');
} catch (e) {
print('Error deleting product: $e');
throw e;
}
}
}
// 购物车服务
class CartService {
final Dio _dio;
CartService(this._dio);
Future<List<CartItem>> getCart() async {
try {
final response = await _dio.get('/cart');
final List<dynamic> data = response.data;
return data.map((item) => CartItem.fromJson(item)).toList();
} catch (e) {
print('Error fetching cart: $e');
throw e;
}
}
Future<CartItem> addToCart(String productId, int quantity) async {
try {
final response = await _dio.post('/cart', data: {
'product_id': productId,
'quantity': quantity,
});
return CartItem.fromJson(response.data);
} catch (e) {
print('Error adding to cart: $e');
throw e;
}
}
Future<void> removeFromCart(String itemId) async {
try {
await _dio.delete('/cart/$itemId');
} catch (e) {
print('Error removing from cart: $e');
throw e;
}
}
Future<CartItem> updateQuantity(String itemId, int quantity) async {
try {
final response = await _dio.put('/cart/$itemId', data: {
'quantity': quantity,
});
return CartItem.fromJson(response.data);
} catch (e) {
print('Error updating quantity: $e');
throw e;
}
}
}
4.2 社交应用网络服务
// 用户服务
class UserService {
final Dio _dio;
UserService(this._dio);
Future<User> login(String email, String password) async {
try {
final response = await _dio.post('/auth/login', data: {
'email': email,
'password': password,
});
// 存储token
final token = response.data['token'];
_dio.options.headers['Authorization'] = 'Bearer $token';
return User.fromJson(response.data['user']);
} catch (e) {
print('Error logging in: $e');
throw e;
}
}
Future<User> register(User user) async {
try {
final response = await _dio.post('/auth/register', data: user.toJson());
return User.fromJson(response.data['user']);
} catch (e) {
print('Error registering: $e');
throw e;
}
}
Future<User> getProfile() async {
try {
final response = await _dio.get('/users/profile');
return User.fromJson(response.data);
} catch (e) {
print('Error fetching profile: $e');
throw e;
}
}
Future<User> updateProfile(User user) async {
try {
final response = await _dio.put('/users/profile', data: user.toJson());
return User.fromJson(response.data);
} catch (e) {
print('Error updating profile: $e');
throw e;
}
}
}
// 帖子服务
class PostService {
final Dio _dio;
PostService(this._dio);
Future<List<Post>> getPosts() async {
try {
final response = await _dio.get('/posts');
final List<dynamic> data = response.data;
return data.map((item) => Post.fromJson(item)).toList();
} catch (e) {
print('Error fetching posts: $e');
throw e;
}
}
Future<Post> createPost(Post post) async {
try {
final response = await _dio.post('/posts', data: post.toJson());
return Post.fromJson(response.data);
} catch (e) {
print('Error creating post: $e');
throw e;
}
}
Future<Post> updatePost(String id, Post post) async {
try {
final response = await _dio.put('/posts/$id', data: post.toJson());
return Post.fromJson(response.data);
} catch (e) {
print('Error updating post: $e');
throw e;
}
}
Future<void> deletePost(String id) async {
try {
await _dio.delete('/posts/$id');
} catch (e) {
print('Error deleting post: $e');
throw e;
}
}
Future<void> likePost(String id) async {
try {
await _dio.post('/posts/$id/like');
} catch (e) {
print('Error liking post: $e');
throw e;
}
}
Future<void> unlikePost(String id) async {
try {
await _dio.delete('/posts/$id/like');
} catch (e) {
print('Error unliking post: $e');
throw e;
}
}
}
// 评论服务
class CommentService {
final Dio _dio;
CommentService(this._dio);
Future<List<Comment>> getComments(String postId) async {
try {
final response = await _dio.get('/posts/$postId/comments');
final List<dynamic> data = response.data;
return data.map((item) => Comment.fromJson(item)).toList();
} catch (e) {
print('Error fetching comments: $e');
throw e;
}
}
Future<Comment> createComment(String postId, String content) async {
try {
final response = await _dio.post('/posts/$postId/comments', data: {
'content': content,
});
return Comment.fromJson(response.data);
} catch (e) {
print('Error creating comment: $e');
throw e;
}
}
Future<void> deleteComment(String commentId) async {
try {
await _dio.delete('/comments/$commentId');
} catch (e) {
print('Error deleting comment: $e');
throw e;
}
}
}
5. 总结
Flutter网络请求的高级技巧包括:
- 使用不同的网络库(http、dio、retrofit)
- 实现拦截器和错误处理
- 使用缓存和文件上传下载
- 管理网络状态
- 组织清晰的网络服务架构
通过掌握这些技巧,你可以创建出更加可靠、高效的Flutter应用,提升用户体验和应用的性能。
更多推荐
所有评论(0)