# ykflutternetworking **Repository Path**: Edwrard/ykflutternetworking ## Basic Information - **Project Name**: ykflutternetworking - **Description**: Flutter 的网络请求库(基于dio进行封装) - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-12-25 - **Last Updated**: 2026-07-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # yknetworking Flutter/Dart 网络请求库,基于 `dio` 5.x 和 `connectivity_plus` 构建。提供统一的 HTTP 请求、拦截器链、重试、取消、上传/下载、动态头/参以及网络连通性监听。 主页与仓库:[https://github.com/yykedward/ykflutternetworking](https://github.com/yykedward/ykflutternetworking) 许可证:MIT ## 特性 - 直接返回 `Future`,无需 `switch`/`when` 解包 —— 失败抛出 `YKNetworkException` - 拦截器链引擎:请求/响应/错误拦截器,优先级排序,类型安全跳过 - 实例级拦截器注册,测试隔离 - 内置拦截器:动态头、动态参数、数据洗练、重定向 - 拦截器内重试 + 外部 `retry()` 两种重试路径 - `CancelToken` 支持,返回 `YKCancelled`(safe API) - 安全 API(`safeRequest()`/`safeUpload()`/`safeDownload()`/`safeRetry()`)返回 `YKResult` 密封类型供需要完全控制的场景 - 上传(`multipart/form-data`)、下载(支持保存到本地) - 全局超时、基础地址、公共参数、公共头配置 - 网络连通性监听 `YKNetworkConnectivity`(基于 `connectivity_plus`) ## 环境与依赖 - Dart `>=3.0.0 <4.0.0` - Flutter - `dio: ^5.5.0` - `connectivity_plus: ^6.0.5` ## 安装 ``` flutter pub add yknetworking ``` 或在 `pubspec.yaml` 中添加: ``` dependencies: yknetworking: ^0.1.6 ``` ## 快速开始 ### 全局配置 ```dart import 'package:yknetworking/yk_networking.dart'; void setupNetworking() { final config = YKNetworkingConfig.getInstance(); config.baseUrl = 'https://api.example.com'; config.timeOut = 30; config.receiveTimeout = 30; config.commHeader = {'Accept': 'application/json'}; config.commParams = {'locale': 'zh-CN'}; } ``` ### Primary API — 直接 await(推荐) ```dart final api = YKNetworking( commonHeader: {'Authorization': 'Bearer token'}, ); try { // 直接获取数据,无需 switch/when final users = await api.get('/users', params: {'page': '1'}); final result = await api.post( '/login', params: {'user': 'admin', 'pwd': 'secret'}, contentType: YKNetworkingContentType.applicationJson, ); final profile = await api.get('/profile'); print(profile.name); } on YKNetworkException catch (e) { print('Request failed: ${e.type} - ${e.message}'); } ``` ### Safe API — 需要 retry 或完全控制时 ```dart final result = await api.safeRequest('/profile', method: YKNetworkingMethod.get); switch (result) { case YKSuccess(:final data, :final statusCode): print('OK $statusCode: $data'); case YKFailure(:final exception, :final retryContext, :final retryCount): if (retryContext != null) { await api.safeRetry(retryContext, headers: {'Authorization': 'Bearer refreshed'}, ); } case YKCancelled(): print('Request cancelled'); } ``` ## 拦截器 ### 自定义拦截器 ```dart class LogInterceptor extends YKInterceptor { @override int get priority => 100; @override String get name => 'logger'; @override YKInterceptorType get type => YKInterceptorType.all; @override Future onRequest(YKNetworkingRequest request) async { print('→ ${request.method.value()} ${request.path}'); } @override Future onResponse(YKInterceptorResponse response) async { print('← ${response.statusCode}'); } } final api = YKNetworking() ..addInterceptor(LogInterceptor()) ..addInterceptor(HandleDataInterceptor( handler: (req, resp) { final d = resp.data; if (d is Map && d['code'] != 0) { return Exception(d['message'] ?? 'business error'); } return null; }, )); ``` ### 拦截器优先级范围 | 范围 | 用途 | |------|------| | 0-99 | 库内置:请求预处理(DynamicHeader、DynamicParams) | | 100-199 | 用户:请求拦截器 | | 200-299 | 用户:响应拦截器 | | 300-399 | 库内置:数据洗练(HandleData) | | 400-499 | 用户:错误拦截器 | | 500-599 | 库内置:重定向 | ### 跳过拦截器 ```dart // 按名称跳过 api.get('/users', skipInterceptors: [const ByName(BuiltInInterceptors.handleData)], ); // 按类型跳过 api.post('/login', skipInterceptors: [const ByType()], ); ``` ## 拦截器内重试 ```dart class TokenRefreshInterceptor extends YKInterceptor { @override int get priority => 400; @override String get name => 'tokenRefresh'; @override YKInterceptorType get type => YKInterceptorType.error; @override Future onError( YKNetworkingRequest request, YKNetworkException error, YKRetryHandler retry, ) async { if (error.statusCode == 401) { final newToken = await refreshToken(); request.commheader!['Authorization'] = 'Bearer $newToken'; await retry(); // 重新执行完整链,自动跳过自身 } } } ``` ## 外部 retry ```dart final result = await api.safeRequest('/profile', method: YKNetworkingMethod.get); if (result case YKFailure(:final retryContext) when retryContext != null) { final newToken = await refreshToken(); // throwing API:直接返回 T final user = await api.retry(retryContext, headers: {'Authorization': 'Bearer $newToken'}, ); } ``` ## 请求取消 ```dart final cancelToken = CancelToken(); final future = api.safeRequest('/slow', method: YKNetworkingMethod.get, cancelToken: cancelToken); cancelToken.cancel('no longer needed'); // 返回 YKCancelled,或 throwing API 抛出 YKNetworkException(type: cancelled) ``` ## 上传与下载 ```dart // 上传 final data = await api.upload( '/files', 'local.png', 'local.png', 'image/png', 'file', params: {'dir': 'images'}, progressCallBack: (sent, total) => print('${sent}/${total}'), ); // 下载到本地 final bytes = await api.download( 'https://host/file.bin', downloadPath: '/tmp/file.bin', progressCallBack: (received, total) => print('${received}/${total}'), ); ``` ## 网络连通性 ```dart final connectivity = YKNetworkConnectivity.getInstance(); await connectivity.setup(); final isOnline = await connectivity.check(); ``` 在 Flutter 中可结合 `ChangeNotifier` 订阅 `didConnect` 状态变化。 ## 生命周期 ```dart final api = YKNetworking() ..addInterceptor(myInterceptor); // 完成后释放资源(取消进行中请求,dispose 所有拦截器) api.dispose(); ``` ## 开发 ```bash flutter test # 运行测试 flutter analyze # 静态分析 ``` ## API 结构 | 文件 | 职责 | |------|------| | `lib/yk_networking.dart` | 公共 API:`YKNetworking` 类(throwing API + `safeRequest()`/`safeUpload()`/`safeDownload()`/`safeRetry()` 安全入口) | | `lib/yk_base_networking.dart` | 静态执行层:拦截器链引擎 + Dio 通信 | | `lib/yk_networking_config.dart` | 单例:全局 Dio 配置 | | `lib/yk_networking_request.dart` | 请求模型 + `YKNetworkingMethod` / `YKNetworkingContentType` | | `lib/yk_result.dart` | `YKResult` 密封类 + `RetryContext` | | `lib/yk_interceptor.dart` | 拦截器抽象类 + `InterceptorRef` + 内置拦截器 | | `lib/yk_interceptor_response.dart` | 响应包装类型 | | `lib/yk_network_exception.dart` | `YKNetworkException` + `YKErrorType` | | `lib/yk_network_connectivity.dart` | 网络连通性监听 | ## 变更日志 见 [CHANGELOG.md](CHANGELOG.md)