855 lines
20 KiB
Markdown
855 lines
20 KiB
Markdown
# Basic Network - 网络通信模块文档
|
||
|
||
## 模块概述
|
||
|
||
`basic_network` 是 OneApp 基础工具模块群中的网络通信核心模块,基于 Dio 框架封装,提供统一的 HTTP 请求接口、拦截器机制、错误处理和日志记录功能。该模块为整个应用提供标准化的网络通信能力。
|
||
|
||
### 基本信息
|
||
- **模块名称**: basic_network
|
||
- **版本**: 0.2.3+4
|
||
- **仓库**: https://gitlab-rd0.maezia.com/eziahz/oneapp/ezia-oneapp-basic-network
|
||
- **Dart 版本**: >=2.17.0 <4.0.0
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
basic_network/
|
||
├── lib/
|
||
│ ├── basic_network.dart # 主导出文件
|
||
│ ├── common_dos.dart # 通用数据对象
|
||
│ ├── common_dtos.dart # 通用数据传输对象
|
||
│ └── src/ # 源代码目录
|
||
│ ├── client/ # HTTP 客户端实现
|
||
│ ├── interceptors/ # 请求拦截器
|
||
│ ├── models/ # 数据模型
|
||
│ ├── exceptions/ # 异常定义
|
||
│ └── utils/ # 工具类
|
||
├── pubspec.yaml # 依赖配置
|
||
└── README.md # 项目说明
|
||
```
|
||
|
||
## 核心功能模块
|
||
|
||
### 1. HTTP 客户端封装
|
||
|
||
基于真实项目的网络引擎架构,使用工厂模式和依赖注入。
|
||
|
||
#### 网络引擎初始化 (`facade.dart`)
|
||
```dart
|
||
// 实际的网络引擎初始化
|
||
bool initNetwork({NetworkEngineOption? option, NetworkLogOutput? networkLog}) =>
|
||
NetworkEngineContext().init(option: option, networkLog: networkLog);
|
||
|
||
/// 根据自定义option获取NetworkEngine
|
||
RequestApi customNetworkEngine(NetworkEngineOption option) =>
|
||
RequestApi(NetworkEngineFactory.createBy(option));
|
||
|
||
/// 统一的请求接口
|
||
Future<T> request<T>(RequestOptions requestOptions) async =>
|
||
NetworkEngineContext.networkEngine.request<T>(requestOptions);
|
||
|
||
/// 带回调的请求方法
|
||
Future<void> requestWithCallback<T>(
|
||
RequestOptions requestOptions,
|
||
RequestOnSuccessCallback<T> onSuccess,
|
||
RequestOnErrorCallback onError,
|
||
) async {
|
||
try {
|
||
final res = await NetworkEngineContext.networkEngine.request<T>(
|
||
requestOptions,
|
||
);
|
||
onSuccess(res);
|
||
} on ErrorBase catch (e) {
|
||
onError(e);
|
||
} catch (e) {
|
||
logger.e(e);
|
||
onError(ErrorGlobalCommon(GlobalCommonErrorType.other, e));
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 默认网络引擎配置 (`common_options.dart`)
|
||
```dart
|
||
// 实际的默认网络引擎选项
|
||
class DefaultNetworkEngineOption extends NetworkEngineOption {
|
||
final Headers _headers = Headers();
|
||
|
||
final BaseDtoResponseConvertor _baseDtoResponseConvertor =
|
||
const DefaultBaseJsonResponseConvertor();
|
||
|
||
final GlobalErrorBusinessFactory _globalBusinessErrorFactory =
|
||
defaultGlobalBusinessErrorFactory;
|
||
|
||
@override
|
||
BaseDtoResponseConvertor get baseDtoConvertor => _baseDtoResponseConvertor;
|
||
|
||
@override
|
||
String get baseUrl => '';
|
||
|
||
@override
|
||
Headers get headers => _headers;
|
||
|
||
@override
|
||
List<Interceptor> get interceptors => [];
|
||
|
||
@override
|
||
ProxyConfig? get proxyConfig => null;
|
||
|
||
@override
|
||
int get receiveTimeout => 10000;
|
||
|
||
@override
|
||
int get retryTime => 3;
|
||
|
||
@override
|
||
int get sendTimeout => 10000;
|
||
|
||
@override
|
||
int get connectTimeout => 10000;
|
||
|
||
@override
|
||
SslConfig? get sslConfig => null;
|
||
|
||
@override
|
||
List<GlobalErrorHandler> get globalErrorHandlers => [];
|
||
|
||
@override
|
||
GlobalErrorBusinessFactory get globalErrorBusinessFactory =>
|
||
_globalBusinessErrorFactory;
|
||
|
||
@override
|
||
bool get debuggable => false;
|
||
|
||
@override
|
||
String get environment => 'sit';
|
||
|
||
@override
|
||
List<PreRequestInterceptor> get preRequestInterceptors => [];
|
||
}
|
||
```
|
||
|
||
#### RequestApi 类实现
|
||
```dart
|
||
// 实际的请求API封装类
|
||
class RequestApi {
|
||
RequestApi(this._engine);
|
||
|
||
final NetworkEngine _engine;
|
||
|
||
/// 异步请求,等待结果或抛出异常
|
||
Future<T> request<T>(RequestOptions requestOptions) async =>
|
||
_engine.request(requestOptions);
|
||
|
||
/// 带回调的请求方法
|
||
Future<void> requestWithCallback<T>(
|
||
RequestOptions requestOptions,
|
||
RequestOnSuccessCallback<T> onSuccess,
|
||
RequestOnErrorCallback onError,
|
||
) async {
|
||
try {
|
||
final res = await _engine.request<T>(requestOptions);
|
||
onSuccess(res);
|
||
} on ErrorBase catch (e) {
|
||
onError(e);
|
||
} catch (e) {
|
||
logger.e(e);
|
||
onError(ErrorGlobalCommon(GlobalCommonErrorType.other, e));
|
||
}
|
||
}
|
||
|
||
/// 文件下载,带进度回调
|
||
Future<HttpResponse> download({
|
||
required dynamic savePath,
|
||
required RequestOptions options,
|
||
ProgressCallback? onReceiveProgress,
|
||
CancelToken? cancelToken,
|
||
}) =>
|
||
_engine.download(
|
||
savePath: savePath,
|
||
options: options,
|
||
onReceiveProgress: onReceiveProgress,
|
||
cancelToken: cancelToken,
|
||
);
|
||
|
||
/// 文件上传,带进度回调
|
||
Future<HttpResponse> upload({
|
||
required RequestOptions options,
|
||
CancelToken? cancelToken,
|
||
ProgressCallback? onSendProgress,
|
||
}) =>
|
||
_engine.upload(
|
||
options: options,
|
||
onSendProgress: onSendProgress,
|
||
cancelToken: cancelToken,
|
||
);
|
||
|
||
/// 获取当前引擎配置
|
||
NetworkEngineOption get option => _engine.option;
|
||
}
|
||
```
|
||
|
||
### 2. 请求拦截器系统
|
||
|
||
#### 请求拦截器
|
||
```dart
|
||
// 请求拦截器
|
||
class RequestInterceptor extends Interceptor {
|
||
@override
|
||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||
// 添加公共请求头
|
||
_addCommonHeaders(options);
|
||
|
||
// 添加认证信息
|
||
_addAuthenticationHeaders(options);
|
||
|
||
// 添加设备信息
|
||
_addDeviceInfo(options);
|
||
|
||
// 请求签名
|
||
_signRequest(options);
|
||
|
||
super.onRequest(options, handler);
|
||
}
|
||
|
||
void _addCommonHeaders(RequestOptions options) {
|
||
options.headers.addAll({
|
||
'User-Agent': _getUserAgent(),
|
||
'Accept-Language': _getAcceptLanguage(),
|
||
'X-Request-ID': _generateRequestId(),
|
||
'X-Timestamp': DateTime.now().millisecondsSinceEpoch.toString(),
|
||
});
|
||
}
|
||
|
||
void _addAuthenticationHeaders(RequestOptions options) {
|
||
final token = AuthManager.instance.accessToken;
|
||
if (token != null) {
|
||
options.headers['Authorization'] = 'Bearer $token';
|
||
}
|
||
}
|
||
|
||
void _addDeviceInfo(RequestOptions options) {
|
||
options.headers.addAll({
|
||
'X-Device-ID': DeviceInfo.instance.deviceId,
|
||
'X-App-Version': AppInfo.instance.version,
|
||
'X-Platform': Platform.isAndroid ? 'android' : 'ios',
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 响应拦截器
|
||
```dart
|
||
// 响应拦截器
|
||
class ResponseInterceptor extends Interceptor {
|
||
@override
|
||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||
// 统一响应格式处理
|
||
_processCommonResponse(response);
|
||
|
||
// 更新认证状态
|
||
_updateAuthenticationStatus(response);
|
||
|
||
// 缓存响应数据
|
||
_cacheResponseIfNeeded(response);
|
||
|
||
super.onResponse(response, handler);
|
||
}
|
||
|
||
void _processCommonResponse(Response response) {
|
||
if (response.data is Map<String, dynamic>) {
|
||
final data = response.data as Map<String, dynamic>;
|
||
|
||
// 检查业务状态码
|
||
final code = data['code'] as int?;
|
||
final message = data['message'] as String?;
|
||
|
||
if (code != null && code != 0) {
|
||
throw BusinessException(code, message ?? '业务处理失败');
|
||
}
|
||
|
||
// 提取实际数据
|
||
if (data.containsKey('data')) {
|
||
response.data = data['data'];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 错误拦截器
|
||
```dart
|
||
// 错误拦截器
|
||
class ErrorInterceptor extends Interceptor {
|
||
@override
|
||
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||
// 网络错误处理
|
||
if (_isNetworkError(err)) {
|
||
_handleNetworkError(err);
|
||
}
|
||
|
||
// 认证错误处理
|
||
if (_isAuthenticationError(err)) {
|
||
_handleAuthenticationError(err);
|
||
}
|
||
|
||
// 服务器错误处理
|
||
if (_isServerError(err)) {
|
||
_handleServerError(err);
|
||
}
|
||
|
||
// 请求重试机制
|
||
if (_shouldRetry(err)) {
|
||
_retryRequest(err, handler);
|
||
return;
|
||
}
|
||
|
||
super.onError(err, handler);
|
||
}
|
||
|
||
bool _shouldRetry(DioException err) {
|
||
// 网络超时重试
|
||
if (err.type == DioExceptionType.connectionTimeout ||
|
||
err.type == DioExceptionType.receiveTimeout) {
|
||
return _getRetryCount(err) < 3;
|
||
}
|
||
|
||
// 5xx 服务器错误重试
|
||
if (err.response?.statusCode != null &&
|
||
err.response!.statusCode! >= 500) {
|
||
return _getRetryCount(err) < 2;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
Future<void> _retryRequest(
|
||
DioException err,
|
||
ErrorInterceptorHandler handler,
|
||
) async {
|
||
final retryCount = _getRetryCount(err) + 1;
|
||
final delay = Duration(seconds: retryCount * 2);
|
||
|
||
await Future.delayed(delay);
|
||
|
||
try {
|
||
final options = err.requestOptions;
|
||
options.extra['retry_count'] = retryCount;
|
||
|
||
final response = await Dio().request(
|
||
options.path,
|
||
data: options.data,
|
||
queryParameters: options.queryParameters,
|
||
options: Options(
|
||
method: options.method,
|
||
headers: options.headers,
|
||
extra: options.extra,
|
||
),
|
||
);
|
||
|
||
handler.resolve(response);
|
||
} catch (e) {
|
||
handler.next(err);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 数据传输对象 (DTOs)
|
||
|
||
#### 通用响应模型
|
||
```dart
|
||
// 通用 API 响应模型
|
||
@freezed
|
||
class ApiResponse<T> with _$ApiResponse<T> {
|
||
const factory ApiResponse({
|
||
required int code,
|
||
required String message,
|
||
T? data,
|
||
@JsonKey(name: 'request_id') String? requestId,
|
||
@JsonKey(name: 'timestamp') int? timestamp,
|
||
}) = _ApiResponse<T>;
|
||
|
||
factory ApiResponse.fromJson(
|
||
Map<String, dynamic> json,
|
||
T Function(Object?) fromJsonT,
|
||
) => _$ApiResponseFromJson(json, fromJsonT);
|
||
}
|
||
|
||
// 分页响应模型
|
||
@freezed
|
||
class PagedResponse<T> with _$PagedResponse<T> {
|
||
const factory PagedResponse({
|
||
required List<T> items,
|
||
required int total,
|
||
required int page,
|
||
required int pageSize,
|
||
@JsonKey(name: 'has_more') required bool hasMore,
|
||
}) = _PagedResponse<T>;
|
||
|
||
factory PagedResponse.fromJson(
|
||
Map<String, dynamic> json,
|
||
T Function(Object?) fromJsonT,
|
||
) => _$PagedResponseFromJson(json, fromJsonT);
|
||
}
|
||
```
|
||
|
||
#### 请求参数模型
|
||
```dart
|
||
// 分页请求参数
|
||
@freezed
|
||
class PageRequest with _$PageRequest {
|
||
const factory PageRequest({
|
||
@Default(1) int page,
|
||
@Default(20) int pageSize,
|
||
String? sortBy,
|
||
@Default('desc') String sortOrder,
|
||
}) = _PageRequest;
|
||
|
||
factory PageRequest.fromJson(Map<String, dynamic> json) =>
|
||
_$PageRequestFromJson(json);
|
||
}
|
||
|
||
// 搜索请求参数
|
||
@freezed
|
||
class SearchRequest with _$SearchRequest {
|
||
const factory SearchRequest({
|
||
required String keyword,
|
||
List<String>? filters,
|
||
@Default(1) int page,
|
||
@Default(20) int pageSize,
|
||
}) = _SearchRequest;
|
||
|
||
factory SearchRequest.fromJson(Map<String, dynamic> json) =>
|
||
_$SearchRequestFromJson(json);
|
||
}
|
||
```
|
||
|
||
### 4. 错误处理系统
|
||
|
||
基于真实项目的多层次错误处理架构,包含全局错误、业务错误和自定义错误。
|
||
|
||
#### 错误基类定义 (`model/error.dart`)
|
||
```dart
|
||
// 实际的错误基类
|
||
abstract class ErrorBase implements Exception {
|
||
/// 调用栈
|
||
StackTrace? stackTrace;
|
||
|
||
/// 错误消息
|
||
String get errorMessage;
|
||
}
|
||
|
||
/// 全局的错误基类
|
||
abstract class ErrorGlobal extends ErrorBase {}
|
||
|
||
/// 通用全局错误
|
||
class ErrorGlobalCommon extends ErrorGlobal {
|
||
ErrorGlobalCommon(
|
||
this.errorType,
|
||
this._originalCause, {
|
||
this.httpCode,
|
||
this.response,
|
||
this.message,
|
||
}) {
|
||
stackTrace = StackTrace.current;
|
||
}
|
||
|
||
/// 封装的原始error
|
||
final dynamic _originalCause;
|
||
|
||
/// 错误类型
|
||
final GlobalCommonErrorType errorType;
|
||
|
||
/// http返回的值
|
||
final int? httpCode;
|
||
|
||
/// 返回的response
|
||
final HttpResponse? response;
|
||
|
||
/// 返回的消息
|
||
late String? message;
|
||
|
||
/// 返回原始的错误原因,如DioError
|
||
dynamic get originalCause => _originalCause;
|
||
|
||
@override
|
||
String get errorMessage => message ?? response?.statusMessage ?? '';
|
||
|
||
@override
|
||
String toString() => 'ErrorGlobalCommon{_originalCause: $_originalCause, '
|
||
'errorType: $errorType, httpCode: $httpCode, response: $response}';
|
||
}
|
||
|
||
/// 业务错误通用基类
|
||
abstract class ErrorGlobalBusiness extends ErrorGlobal {
|
||
/// 业务错误码
|
||
String get businessCode;
|
||
|
||
@override
|
||
String get errorMessage;
|
||
|
||
/// 错误配置
|
||
Map<String, dynamic> get errorConfig;
|
||
|
||
@override
|
||
String toString() =>
|
||
'ErrorGlobalBusiness{businessCode:$businessCode, message:$errorMessage}';
|
||
}
|
||
|
||
/// 自定义错误
|
||
class ErrorCustom extends ErrorBase {
|
||
// 自定义错误实现
|
||
// ...
|
||
}
|
||
```
|
||
|
||
#### 全局错误处理器
|
||
```dart
|
||
// 错误工厂方法类型定义
|
||
typedef GlobalErrorBusinessFactory = ErrorGlobalBusiness? Function(
|
||
BaseDtoModel model,
|
||
);
|
||
|
||
typedef CustomErrorFactory = ErrorCustom? Function(BaseDtoModel model);
|
||
|
||
// 全局错误处理流程
|
||
// 在网络引擎中自动调用错误处理器链
|
||
// 支持自定义全局错误处理器扩展
|
||
```
|
||
|
||
#### 错误类型枚举
|
||
```dart
|
||
// 全局通用错误类型
|
||
enum GlobalCommonErrorType {
|
||
timeout,
|
||
noNetwork,
|
||
serverError,
|
||
parseError,
|
||
other,
|
||
}
|
||
```
|
||
|
||
### 5. 缓存机制
|
||
|
||
#### 请求缓存管理
|
||
```dart
|
||
// 网络缓存管理器
|
||
class NetworkCacheManager {
|
||
static final Map<String, CacheItem> _cache = {};
|
||
static const Duration defaultCacheDuration = Duration(minutes: 5);
|
||
|
||
// 设置缓存
|
||
static void setCache(
|
||
String key,
|
||
dynamic data, {
|
||
Duration? duration,
|
||
}) {
|
||
_cache[key] = CacheItem(
|
||
data: data,
|
||
timestamp: DateTime.now(),
|
||
duration: duration ?? defaultCacheDuration,
|
||
);
|
||
}
|
||
|
||
// 获取缓存
|
||
static T? getCache<T>(String key) {
|
||
final item = _cache[key];
|
||
if (item == null) return null;
|
||
|
||
if (item.isExpired) {
|
||
_cache.remove(key);
|
||
return null;
|
||
}
|
||
|
||
return item.data as T?;
|
||
}
|
||
|
||
// 清除缓存
|
||
static void clearCache([String? key]) {
|
||
if (key != null) {
|
||
_cache.remove(key);
|
||
} else {
|
||
_cache.clear();
|
||
}
|
||
}
|
||
|
||
// 生成缓存键
|
||
static String generateCacheKey(
|
||
String path,
|
||
Map<String, dynamic>? queryParameters,
|
||
) {
|
||
final uri = Uri(path: path, queryParameters: queryParameters);
|
||
return uri.toString();
|
||
}
|
||
}
|
||
|
||
// 缓存项
|
||
class CacheItem {
|
||
final dynamic data;
|
||
final DateTime timestamp;
|
||
final Duration duration;
|
||
|
||
CacheItem({
|
||
required this.data,
|
||
required this.timestamp,
|
||
required this.duration,
|
||
});
|
||
|
||
bool get isExpired => DateTime.now().difference(timestamp) > duration;
|
||
}
|
||
```
|
||
|
||
### 6. 请求配置管理
|
||
|
||
#### 环境配置
|
||
```dart
|
||
// 网络环境配置
|
||
enum NetworkEnvironment {
|
||
development,
|
||
testing,
|
||
staging,
|
||
production,
|
||
}
|
||
|
||
class NetworkConfig {
|
||
final String baseUrl;
|
||
final Duration connectTimeout;
|
||
final Duration receiveTimeout;
|
||
final Duration sendTimeout;
|
||
final bool enableLogging;
|
||
final bool enableCache;
|
||
final int maxRetries;
|
||
|
||
const NetworkConfig({
|
||
required this.baseUrl,
|
||
this.connectTimeout = const Duration(seconds: 30),
|
||
this.receiveTimeout = const Duration(seconds: 30),
|
||
this.sendTimeout = const Duration(seconds: 30),
|
||
this.enableLogging = false,
|
||
this.enableCache = true,
|
||
this.maxRetries = 3,
|
||
});
|
||
|
||
// 开发环境配置
|
||
static const NetworkConfig development = NetworkConfig(
|
||
baseUrl: 'https://dev-api.oneapp.com',
|
||
enableLogging: true,
|
||
enableCache: false,
|
||
);
|
||
|
||
// 测试环境配置
|
||
static const NetworkConfig testing = NetworkConfig(
|
||
baseUrl: 'https://test-api.oneapp.com',
|
||
enableLogging: true,
|
||
);
|
||
|
||
// 生产环境配置
|
||
static const NetworkConfig production = NetworkConfig(
|
||
baseUrl: 'https://api.oneapp.com',
|
||
enableLogging: false,
|
||
);
|
||
|
||
static NetworkConfig forEnvironment(NetworkEnvironment env) {
|
||
switch (env) {
|
||
case NetworkEnvironment.development:
|
||
return development;
|
||
case NetworkEnvironment.testing:
|
||
return testing;
|
||
case NetworkEnvironment.staging:
|
||
return testing; // 使用测试环境配置
|
||
case NetworkEnvironment.production:
|
||
return production;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 使用示例
|
||
|
||
基于实际项目的网络请求使用方法。
|
||
|
||
### 基本初始化和使用
|
||
```dart
|
||
// 初始化网络库
|
||
final option = DefaultNetworkEngineOption()
|
||
..baseUrl = 'https://api.oneapp.com'
|
||
..debuggable = true
|
||
..environment = 'production';
|
||
|
||
// 初始化默认网络引擎
|
||
initNetwork(option: option);
|
||
|
||
// 直接使用全局方法发起请求
|
||
try {
|
||
final response = await request<UserModel>(
|
||
RequestOptions(
|
||
path: '/users/profile',
|
||
method: 'GET',
|
||
),
|
||
);
|
||
print('用户信息: ${response.name}');
|
||
} on ErrorBase catch (e) {
|
||
print('请求失败: ${e.errorMessage}');
|
||
}
|
||
```
|
||
|
||
### 使用RequestApi
|
||
```dart
|
||
// 创建自定义网络引擎
|
||
final customOption = DefaultNetworkEngineOption()
|
||
..baseUrl = 'https://custom-api.com'
|
||
..retryTime = 5
|
||
..connectTimeout = 15000;
|
||
|
||
final api = customNetworkEngine(customOption);
|
||
|
||
// 使用回调方式处理请求
|
||
await api.requestWithCallback<List<ArticleModel>>(
|
||
RequestOptions(
|
||
path: '/articles',
|
||
method: 'GET',
|
||
queryParameters: {'page': 1, 'limit': 20},
|
||
),
|
||
(articles) {
|
||
print('获取到 ${articles.length} 篇文章');
|
||
},
|
||
(error) {
|
||
print('请求失败: ${error.errorMessage}');
|
||
|
||
// 处理特定类型的错误
|
||
if (error is ErrorGlobalBusiness) {
|
||
print('业务错误码: ${error.businessCode}');
|
||
}
|
||
},
|
||
);
|
||
```
|
||
|
||
### 文件上传和下载
|
||
```dart
|
||
// 文件上传
|
||
final uploadResponse = await api.upload(
|
||
options: RequestOptions(
|
||
path: '/upload',
|
||
method: 'POST',
|
||
data: FormData.fromMap({
|
||
'file': await MultipartFile.fromFile('/path/to/file.jpg'),
|
||
'description': '头像上传',
|
||
}),
|
||
),
|
||
onSendProgress: (sent, total) {
|
||
final progress = (sent / total * 100).toStringAsFixed(1);
|
||
print('上传进度: $progress%');
|
||
},
|
||
);
|
||
|
||
// 文件下载
|
||
await download(
|
||
savePath: '/path/to/save/file.pdf',
|
||
options: RequestOptions(
|
||
path: '/download/document.pdf',
|
||
method: 'GET',
|
||
),
|
||
onReceiveProgress: (received, total) {
|
||
final progress = (received / total * 100).toStringAsFixed(1);
|
||
print('下载进度: $progress%');
|
||
},
|
||
);
|
||
```
|
||
|
||
### 自定义配置示例
|
||
```dart
|
||
// 创建带有自定义拦截器的配置
|
||
class MyNetworkOption extends DefaultNetworkEngineOption {
|
||
@override
|
||
String get baseUrl => 'https://my-api.com';
|
||
|
||
@override
|
||
List<Interceptor> get interceptors => [
|
||
MyAuthInterceptor(),
|
||
MyLoggingInterceptor(),
|
||
];
|
||
|
||
@override
|
||
List<GlobalErrorHandler> get globalErrorHandlers => [
|
||
MyCustomErrorHandler(),
|
||
];
|
||
|
||
@override
|
||
bool get debuggable => kDebugMode;
|
||
|
||
@override
|
||
int get retryTime => 3;
|
||
}
|
||
```
|
||
|
||
## 依赖管理
|
||
|
||
基于实际的pubspec.yaml配置,展示真实的项目依赖关系。
|
||
|
||
### 核心依赖
|
||
```yaml
|
||
# 实际项目依赖配置
|
||
dependencies:
|
||
http_parser: ^4.0.2 # HTTP 解析工具
|
||
dio: ^5.7.0 # HTTP 客户端库(核心)
|
||
pretty_dio_logger: ^1.3.1 # 美化的请求日志
|
||
freezed_annotation: ^2.2.0 # 不可变类注解
|
||
json_annotation: ^4.8.1 # JSON 序列化注解
|
||
|
||
dev_dependencies:
|
||
json_serializable: ^6.7.0 # JSON 序列化生成器
|
||
build_runner: ^2.4.5 # 代码生成引擎
|
||
test: ^1.24.3 # 单元测试框架
|
||
coverage: ^1.6.3 # 测试覆盖率工具
|
||
freezed: ^2.3.5 # 不可变类生成器
|
||
flutter_lints: ^5.0.0 # 代码规范检查
|
||
```
|
||
|
||
### 实际的版本信息
|
||
- **模块名称**: basic_network
|
||
- **版本**: 0.2.3+4
|
||
- **仓库**: https://gitlab-rd0.maezia.com/eziahz/oneapp/ezia-oneapp-basic-network
|
||
- **Dart 版本**: >=2.17.0 <4.0.0
|
||
|
||
## 性能优化
|
||
|
||
### 网络性能优化
|
||
- 连接池复用
|
||
- HTTP/2 支持
|
||
- 请求合并和批处理
|
||
- 智能重试机制
|
||
|
||
### 缓存优化
|
||
- 多级缓存策略
|
||
- 缓存过期管理
|
||
- 条件请求支持
|
||
- 离线缓存机制
|
||
|
||
### 内存优化
|
||
- 流式数据处理
|
||
- 大文件分块传输
|
||
- 及时释放响应数据
|
||
- 内存泄漏检测
|
||
|
||
## 测试策略
|
||
|
||
### 单元测试
|
||
- 网络服务接口测试
|
||
- 拦截器功能测试
|
||
- 错误处理测试
|
||
- 缓存机制测试
|
||
|
||
### 集成测试
|
||
- 端到端请求测试
|
||
- 网络环境切换测试
|
||
- 错误恢复测试
|
||
|
||
### Mock 测试
|
||
- 网络请求 Mock
|
||
- 错误场景模拟
|
||
- 性能测试
|
||
|
||
## 总结
|
||
|
||
`basic_network` 模块为 OneApp 提供了强大而灵活的网络通信能力。通过统一的接口抽象、完善的错误处理、智能的缓存机制和丰富的拦截器功能,大大简化了网络请求的开发工作,提高了应用的稳定性和用户体验。模块的设计充分考虑了可扩展性和可维护性,为大型应用的网络通信提供了坚实的基础。
|