元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
Flutter基础
环境搭建与第一个应用
Dart语言快速入门
Flutter项目结构解析
▶
Widgets与布局
常用Widgets介绍
布局Widgets详解
自定义Widget创建
▶
状态管理
StatefulWidget与状态管理基础
Provider状态管理实战
BLoC模式入门
▶
导航与路由
页面导航基础
命名路由与参数传递
底部导航栏实现
▶
网络与数据存储
HTTP请求与Dio库使用
本地存储(SharedPreferences/SQLite)
Firebase集成指南
▶
打包与发布
Android应用打包
iOS应用打包
应用发布到商店指南
发布时间:
2025-03-22 22:36
↑
☰
# Flutter HTTP请求与Dio库使用 ## HTTP请求基础 在Flutter中进行网络请求有多种方式: 1. 使用`http`包(官方基础包) 2. 使用`dio`包(功能更强大的第三方包) 3. 使用`HttpClient`(dart:io提供的底层API) 本文主要介绍功能强大且使用广泛的Dio库。 ## Dio库介绍 Dio是一个强大的Dart Http请求库,支持: - 请求拦截器 - 全局配置 - FormData上传文件 - 请求取消 - Cookie管理 - 使用适配器自定义底层实现 - 等等 ### 添加依赖 ```yaml dependencies: dio: ^5.3.2 ``` ### 基本使用 ```dart import 'package:dio/dio.dart'; // 创建dio实例 final dio = Dio(); // 基本GET请求 Future<void> getRequest() async { try { final response = await dio.get('https://api.example.com/data'); print(response.data); } catch (e) { print('Error: $e'); } } // 带参数的GET请求 Future<void> getWithParams() async { try { final response = await dio.get( 'https://api.example.com/data', queryParameters: { 'id': 12, 'name': 'test', }, ); print(response.data); } catch (e) { print('Error: $e'); } } // POST请求 Future<void> postRequest() async { try { final response = await dio.post( 'https://api.example.com/post', data: { 'title': 'test', 'body': 'hello world', }, ); print(response.data); } catch (e) { print('Error: $e'); } } ``` ## 高级配置 ### 全局配置 ```dart final dio = Dio(BaseOptions( baseUrl: 'https://api.example.com', connectTimeout: Duration(seconds: 5), receiveTimeout: Duration(seconds: 3), headers: { 'Authorization': 'Bearer your_token_here', 'Accept': 'application/json', }, )); ``` ### 拦截器使用 ```dart class LogInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { print('REQUEST[${options.method}] => PATH: ${options.path}'); return super.onRequest(options, handler); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { print('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}'); return super.onResponse(response, handler); } @override void onError(DioException err, ErrorInterceptorHandler handler) { print('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}'); return super.onError(err, handler); } } // 添加拦截器 dio.interceptors.add(LogInterceptor()); ``` ### 文件上传 ```dart Future<void> uploadFile() async { try { final formData = FormData.fromMap({ 'file': await MultipartFile.fromFile( './text.txt', filename: 'text.txt', ), 'files': [ await MultipartFile.fromFile( './text1.txt', filename: 'text1.txt', ), await MultipartFile.fromFile( './text2.txt', filename: 'text2.txt', ), ], }); final response = await dio.post( '/upload', data: formData, onSendProgress: (int sent, int total) { print('$sent $total'); }, ); print(response.data); } catch (e) { print('Error: $e'); } } ``` ### 下载文件 ```dart Future<void> downloadFile() async { try { await dio.download( 'https://example.com/file.pdf', './file.pdf', onReceiveProgress: (received, total) { if (total != -1) { print((received / total * 100).toStringAsFixed(0) + "%"); } }, ); } catch (e) { print('Error: $e'); } } ``` ## 错误处理 ### 统一错误处理 ```dart class ApiService { final Dio _dio; ApiService() : _dio = Dio() { _dio.options.baseUrl = 'https://api.example.com'; _dio.options.connectTimeout = Duration(seconds: 5); _dio.options.receiveTimeout = Duration(seconds: 3); _dio.interceptors.add( InterceptorsWrapper( onError: (DioException error, handler) async { switch (error.type) { case DioExceptionType.connectionTimeout: case DioExceptionType.sendTimeout: case DioExceptionType.receiveTimeout: // 超时错误处理 throw TimeoutException('请求超时'); case DioExceptionType.badResponse: // 服务器错误处理 switch (error.response?.statusCode) { case 400: throw BadRequestException('请求参数错误'); case 401: throw UnauthorizedException('未授权'); case 403: throw ForbiddenException('禁止访问'); case 404: throw NotFoundException('请求地址不存在'); case 500: throw ServerException('服务器内部错误'); default: throw UnknownException('未知错误'); } case DioExceptionType.cancel: throw RequestCancelledException('请求被取消'); default: throw UnknownException('未知错误'); } }, ), ); } Future<T> get<T>(String path, { Map<String, dynamic>? queryParameters, Options? options, CancelToken? cancelToken, }) async { try { final response = await _dio.get<T>( path, queryParameters: queryParameters, options: options, cancelToken: cancelToken, ); return response.data as T; } catch (e) { rethrow; } } // 其他请求方法类似... } // 自定义异常 class ApiException implements Exception { final String message; ApiException(this.message); } class TimeoutException extends ApiException { TimeoutException(String message) : super(message); } class BadRequestException extends ApiException { BadRequestException(String message) : super(message); } // 使用示例 final apiService = ApiService(); try { final data = await apiService.get<Map<String, dynamic>>('/users/1'); print(data); } on TimeoutException catch (e) { print('超时错误:${e.message}'); } on BadRequestException catch (e) { print('请求参数错误:${e.message}'); } catch (e) { print('其他错误:$e'); } ``` ## 最佳实践 ### 1. 创建API服务类 ```dart class ApiService { static final ApiService _instance = ApiService._internal(); factory ApiService() => _instance; late final Dio _dio; ApiService._internal() { _dio = Dio(BaseOptions( baseUrl: 'https://api.example.com', connectTimeout: Duration(seconds: 5), receiveTimeout: Duration(seconds: 3), headers: { 'Accept': 'application/json', }, )); // 添加拦截器 _dio.interceptors.add(LogInterceptor()); } // 用户相关API Future<User> getUserProfile(String userId) async { try { final response = await _dio.get('/users/$userId'); return User.fromJson(response.data); } catch (e) { throw _handleError(e); } } Future<List<Post>> getUserPosts(String userId) async { try { final response = await _dio.get('/users/$userId/posts'); return (response.data as List) .map((json) => Post.fromJson(json)) .toList(); } catch (e) { throw _handleError(e); } } // 统一错误处理 Exception _handleError(dynamic error) { if (error is DioException) { // 处理Dio错误 return ApiException(error.message ?? '未知错误'); } return Exception('未知错误'); } } ``` ### 2. 使用Repository模式 ```dart // 定义仓库接口 abstract class UserRepository { Future<User> getUserProfile(String userId); Future<List<Post>> getUserPosts(String userId); } // 实现仓库接口 class UserRepositoryImpl implements UserRepository { final ApiService _apiService; UserRepositoryImpl(this._apiService); @override Future<User> getUserProfile(String userId) { return _apiService.getUserProfile(userId); } @override Future<List<Post>> getUserPosts(String userId) { return _apiService.getUserPosts(userId); } } // 在BLoC或Provider中使用 class UserBloc extends Cubit<UserState> { final UserRepository _userRepository; UserBloc(this._userRepository) : super(UserInitial()); Future<void> loadUserProfile(String userId) async { try { emit(UserLoading()); final user = await _userRepository.getUserProfile(userId); emit(UserLoaded(user)); } catch (e) { emit(UserError(e.toString())); } } } ``` ### 3. 缓存处理 ```dart class CacheInterceptor extends Interceptor { final _cache = <String, Response>{}; @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { // 只缓存GET请求 if (options.method == 'GET') { final response = _cache[options.uri.toString()]; if (response != null) { return handler.resolve(response); } } return super.onRequest(options, handler); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { // 缓存响应 if (response.requestOptions.method == 'GET') { _cache[response.requestOptions.uri.toString()] = response; } return super.onResponse(response, handler); } } // 使用缓存拦截器 dio.interceptors.add(CacheInterceptor()); ``` ### 4. 请求重试 ```dart class RetryInterceptor extends Interceptor { final int maxRetries; final Duration retryDelay; RetryInterceptor({ this.maxRetries = 3, this.retryDelay = const Duration(seconds: 1), }); @override Future onError(DioException err, ErrorInterceptorHandler handler) async { var retryCount = 0; final requestOptions = err.requestOptions; while (retryCount < maxRetries) { try { retryCount++; print('重试第$retryCount次'); // 等待一段时间后重试 await Future.delayed(retryDelay); final response = await Dio().fetch(requestOptions); return handler.resolve(response); } catch (e) { if (retryCount >= maxRetries) { return super.onError(err, handler); } } } } } // 使用重试拦截器 dio.interceptors.add(RetryInterceptor()); ``` ## 总结 本文详细介绍了Flutter中使用Dio库进行网络请求的方法,包括: 1. 基本的GET、POST请求 2. 文件上传下载 3. 拦截器使用 4. 错误处理 5. 最佳实践 建议: - 统一管理API请求 - 实现适当的错误处理 - 使用拦截器优化请求流程 - 考虑缓存策略 - 实现请求重试机制 - 遵循代码组织最佳实践