网络请求
概述
本文档详细介绍了FluCli项目模板中的网络请求框架,基于Dio和hzy_normal_network库实现,提供了完整的HTTP请求、缓存管理和错误处理解决方案。
网络架构概述
核心组件
- HTTP配置管理:环境切换、域名配置
- 网络请求封装:统一的请求接口
- 缓存策略:基于Dio Cache Interceptor的缓存管理
- 错误处理:统一的错误处理机制
- 拦截器支持:请求/响应拦截器
技术栈
组件 | 技术 | 说明 |
---|---|---|
HTTP客户端 | Dio | 强大的HTTP客户端 |
网络框架 | hzy_normal_network | 封装的网络请求框架 |
缓存管理 | dio_cache_interceptor | HTTP缓存拦截器 |
本地存储 | Hive | 轻量级数据库 |
HTTP配置管理
环境配置
文件定义了完整的HTTP配置:dart
// 环境枚举
enum HttpEnvironEnmu {
debug, // 开发环境
release, // 发布环境
}
// 域名枚举
enum HttpBaseUrlEnum {
normalUrl, // 默认域名
otherUrl, // 其他域名
}
class HttpNormalConfig {
// 当前环境配置
static const HttpEnvironEnmu environ = HttpEnvironEnmu.release;
// 获取完整URL
static String conFigNetWorkPath({
required String path,
HttpBaseUrlEnum urlEnum = HttpBaseUrlEnum.normalUrl,
HttpEnvironEnmu environEnmu = HttpNormalConfig.environ,
}) {
String baseurl = configbaseUrl(
urlEnum: urlEnum,
environEnmu: environ,
);
return baseurl + path;
}
}
域名配置
dart
// 开发环境域名配置
static String configDebugBaseUrl({
HttpBaseUrlEnum urlEnum = HttpBaseUrlEnum.normalUrl,
}) {
switch (urlEnum) {
case HttpBaseUrlEnum.normalUrl:
return "http://dev.example.com/api";
case HttpBaseUrlEnum.otherUrl:
return "http://dev-other.example.com/api";
}
}
// 生产环境域名配置
static String configReleaseBaseUrl({
HttpBaseUrlEnum urlEnum = HttpBaseUrlEnum.normalUrl,
}) {
switch (urlEnum) {
case HttpBaseUrlEnum.normalUrl:
return "https://api.example.com";
case HttpBaseUrlEnum.otherUrl:
return "https://api-other.example.com";
}
}
网络请求封装
请求工具类
提供了统一的网络请求接口:dart
class NetWorkInstance {
static final NetWorkInstance _instance = NetWorkInstance._internal();
factory NetWorkInstance() => _instance;
HzyNormalClient? _client;
// 配置网络客户端
configClient({required HzyNormalHttpConfig config}) {
_client = HzyNormalClient(normalHttpConfig: config);
}
// 获取客户端实例
HzyNormalClient? getClient() {
if (_client == null) {
throw Exception("请先配置网络请求");
}
return _client;
}
}
通用请求方法
dart
/// 通用网络请求方法
Future<HzyNormalResponse> request({
required String path, // 请求路径
dynamic data, // 请求参数
Method method = Method.get, // 请求方式
bool isShowLoad = true, // 是否显示加载动画
bool isUpdateCaChe = true, // 是否更新缓存
bool isShowError = true, // 是否显示错误提示
bool isShowSuccessToast = false, // 是否显示成功提示
bool isNeedGlobalParams = false, // 是否需要全局参数
HzyNormalTransFormer? httpTransformer, // 拦截器
CachePolicy? policy, // 缓存策略
Options? options, // 请求选项
}) async {
// 请求实现
}
缓存管理
缓存配置
提供了完整的缓存管理:dart
class DioCacheTool {
static late CacheStore _cacheStore;
static late CacheOptions cacheOptions;
// 初始化缓存存储
static Future<void> initCacheStore() async {
final dir = await getApplicationDocumentsDirectory();
_cacheStore = HiveCacheStore(
await Hive.openBox(
"hzy_basic_http_cache",
path: dir.path,
),
);
}
// 初始化缓存拦截器
static DioCacheInterceptor init() {
cacheOptions = CacheOptions(
store: _cacheStore,
policy: CachePolicy.request,
hitCacheOnErrorExcept: [401, 403],
maxStale: const Duration(days: 7),
priority: CachePriority.normal,
cipher: null,
keyBuilder: CacheOptions.defaultCacheKeyBuilder,
allowPostMethod: false,
);
return DioCacheInterceptor(options: cacheOptions);
}
}
缓存策略
策略 | 说明 | 适用场景 |
---|---|---|
forceCache | 强制缓存,保存所有成功的GET请求 | 静态数据 |
refreshForceCache | 刷新强制缓存 | 需要最新数据但允许缓存 |
noCache | 不使用缓存 | 实时数据 |
refresh | 刷新请求,忽略缓存 | 下拉刷新 |
request | 优先使用缓存,过期时请求新数据 | 一般数据 |
缓存操作
dart
// 获取缓存响应
static Future<CacheResponse?> getHttpCacheResponse({
required String url,
required String method,
Map<String, dynamic>? queryParameters,
}) async {
// 实现缓存获取逻辑
}
// 清除所有HTTP缓存
static clearHttpCache() async {
await _cacheStore.clean();
}
// 清除指定URL的缓存
static clearUrlHttpCache({required String url}) async {
await _cacheStore.delete(url);
}
API接口实现
API类设计
展示了标准的API接口实现:dart
class EgApis {
/// 加载列表数据
Future<dynamic> loadListData({
int page = 1,
int? lastPostId,
bool isShowLoad = false,
}) async {
Map<String, dynamic> data = {
"page": page,
"type": "loadmore",
};
if (lastPostId != null) {
data["post_id"] = lastPostId;
}
return await request(
path: "/tc/list",
data: data,
isShowLoad: isShowLoad,
isShowError: false,
method: Method.get,
policy: isShowLoad
? CachePolicy.refreshForceCache
: CachePolicy.forceCache,
options: Options(
sendTimeout: lastPostId != null
? const Duration(milliseconds: 3000)
: null,
),
);
}
}
API使用示例
dart
class DemoController extends BaseGetXController {
final EgApis _api = EgApis();
@override
Future<void> getNetWorkData({int? type, Map<String, dynamic>? info}) async {
try {
final response = await _api.loadListData(
page: currentPage.value,
isShowLoad: type == 3,
);
if (response.isSuccess) {
// 处理成功响应
handleSuccessResponse(response.data);
} else {
// 处理错误响应
handleErrorResponse(response.error);
}
} catch (e) {
// 处理异常
handleException(e);
}
}
}
网络初始化
应用启动配置
在中进行网络初始化:
dart
class LaunchConfig {
static Future<void> init() async {
// 初始化缓存存储
await DioCacheTool.initCacheStore();
// 初始化网络配置
await initNetWork();
}
static Future<void> initNetWork() async {
// 配置响应转换器
HzyNormalDefaultTransFormer.getInstance().setHttpConfig(
config: HzyNormalHttpResponeConfig(
successCode: 200,
successField: "code",
msgField: "msg",
dataField: "data",
),
);
// 配置网络客户端
NetWorkInstance().configClient(
config: HzyNormalHttpConfig(
baseUrl: HttpNormalConfig.configbaseUrl(),
connectTimeout: const Duration(milliseconds: 30000),
receiveTimeout: const Duration(milliseconds: 30000),
interceptors: [
DioCacheTool.init(), // 添加缓存拦截器
],
),
);
}
}
错误处理
统一错误处理
dart
// 在请求方法中的错误处理
if (!res.isSuccess) {
if (isShowError) {
EasyLoading.showError(
res.error?.msg ?? "网络请求失败",
);
}
return HzyNormalResponse.fail(
msg: res.error?.msg ?? "NetWork Fail",
code: res.error?.code ?? -1,
);
}
错误类型
错误类型 | 处理方式 | 说明 |
---|---|---|
网络超时 | 自动重试 | 连接超时或读取超时 |
服务器错误 | 显示错误信息 | 5xx状态码 |
客户端错误 | 显示错误信息 | 4xx状态码 |
解析错误 | 显示通用错误 | JSON解析失败 |
最佳实践
开发建议
环境配置
- 开发和生产环境使用不同的域名
- 通过环境变量控制当前环境
- 支持多域名切换
缓存策略
- 静态数据使用强制缓存
- 动态数据使用请求缓存
- 实时数据不使用缓存
错误处理
- 统一错误处理机制
- 友好的错误提示
- 适当的重试策略
性能优化
请求优化
- 合理设置超时时间
- 使用连接池复用连接
- 压缩请求和响应数据
缓存优化
- 设置合理的缓存过期时间
- 定期清理过期缓存
- 控制缓存大小
内存管理
- 及时释放大文件下载的内存
- 避免内存泄漏
- 合理使用单例模式
安全考虑
HTTPS使用
- 生产环境强制使用HTTPS
- 证书验证
- 防止中间人攻击
数据安全
- 敏感数据加密传输
- API密钥安全存储
- 请求签名验证