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应用,提升用户体验和应用的性能。
