个人使用flutter开发项目已经有1年半的时间了,由于从iOS原生开发转使用Flutter,比较习惯使用数据模型,但是没有发现一个比较好的数据转模型的组件。于是自己动手封装了一个package,在公司的项目下使用了半年的时间,经过改良也算能够满足日常的使用需求,由于不涉及任何业务代码,就开源出来给大家参考一下。
fx_http
一个基础的flutter网络请求工具,包含多种请求方式,自动数据转模型
可在 pub.dev 搜索 'fx_http' 使用
核心类 DioUtil
1、配置 -- 使用前必须先初始化,指定接口服务器地址:
/// 初始化DioUtil的参数 (也可以使用initOption) **** 切记在使用DioUtils前初始化,推荐在main入口函数中调用 ****
/// baseUrl 请求地址
/// isDebugMode 调试模式, debug时会打印接口日志到控制台,弹出接口错误提示
/// apiSuccessCode api接口正确码
/// sendTimeout 发送超时时间 (秒)
/// connectTimeout 请求超时时间 (秒)
/// receiveTimeout 接收超时时间 (秒)
/// validateApiSuccess 根据返回的数据判断是否请求成功的闭包
static init(String baseUrl, {bool isDebugMode = false, int apiSuccessCode = 0, int sendTimeout = 15, int connectTimeout = 15, int receiveTimeout = 15, ValidateApiSuccess? validateApiSuccess});
/// 初始化
DioUtils.init("https://github.com/", isDebugMode: true, apiSuccessCode: 0);
也可以使用 DioUtils.initOption 初始化,自由度更高。
1.1 可以开启debugMode下的控制台日志,使用前必须初始化打印工具(推荐在main入口函数中调用),可以指定tag, 指定运行模式(release模式下,Log.e, Log.json 不会在控制台输出):
Log.init(tag: 'fx_http', isDebug: true);
Log.d('Hello, Flutter Developers');
/// 是否开启控制台日志 - 仅针对debug|profile(release模式下默认关闭)
void enableConsoleLogging({bool enable = true})
1.2、如果需要切换接口的服务器地址,可以使用updateOptions方法来修改,后面所有的接口请求都会使用新的地址发器请求。
/// 更改设置 (这里的更改是全局的 ====== 请注意使用)
/// baseUrl 请求地址
/// headers 请求头
void updateOptions({String? baseUrl, Map? headers});
1.3、添加拦截器(可以添加拦截器用于在请求发起前,或者收到response后做一些事情)
/// 添加自定义拦截器 (可以添加请求头)
void addInterceptors(Interceptor interceptor)
1.4、开启代理抓包,可用于测试接口
/// 开启抓包 (仅适用于非web端)
void openProxy(String proxyIp, int proxyPort);
// 关闭抓包
void closeProxy();
1.5、如果想取消所有请求,可以使用cancelAllRequest,如果想取消特定请求,可以使用cancelRequest
/// 取消所有请求
void cancelAllRequest();
/// 根据请求地址取消特定请求 (请求)
/// url 请求路径 比如:'trade/open'
bool cancelRequest({String? url})
2、发起请求,主要有四个方法可以使用:
2.1 异步请求方式,采用异步回调的方式返回结果,数据直接在onSuccess、onSuccessList或者onPageSuccessList中获取。单个请求时可用这个方法,如果有多个请求互相依赖时使用这种方式会形成嵌套调用,就不推荐了。
/// brief http请求 (通过回调函数回调结果)
/// @param method 请求方式
/// @param api 接口地址
/// @param params post请求参数
/// @param queryParameters get请求参数
/// @param isShow 请求时是否显示吐司
/// @param isPageData 是否是分页数据
/// @param isList 是否是列表数据
/// @param model 要解析的数据模型
/// @param onSuccess 请求成功回调 (返回数据)
/// @param onSuccessList 请求成功回调 (返回列表数据)
/// @param onPageSuccessList 请求成功回调 (返回分页列表数据)
/// @param onError 请求失败回调
/// @param cancelToken 取消请求的token
/// @param options 对请求的设置
void asyncRequestNetwork(Method method, String api, {
dynamic params,
Map? queryParameters,
bool isShow : false, // 是否显示加载吐司
bool isPageData : false, // 是否是分页数据
bool isList : false,
BaseModel? model,
Function(T? t)? onSuccess,
Function(List list)? onSuccessList,
Function(List list, int total, int perPage, int currentPage)? onPageSuccessList,
Function(int code, String msg)? onError,
CancelToken? cancelToken,
Options? options
});
2.2 Future请求方式,可以使用await阻塞同步返回结果,也可以使用then异步返回结果。单个、多个都可以使用该方法,数据需要自己从返回值里面取一下。 特别适用于FutureBuilder构建的组建中。
/// brief http请求 (通过Future方式请求,可以使用await阻塞直到获取到结果)
/// @param method 请求方式
/// @param url 接口地址
/// @param isPageData 是否是分页数据
/// @param params post请求参数
/// @param queryParameters get请求参数
/// @param model 要解析的数据模型
/// @param cancelToken 取消请求的token
/// @param options 对请求的设置
Future> requestNetwork(Method method, String url, {
bool isPageData = false,
bool isShow = false, // 是否显示加载吐司
dynamic params,
Map? queryParameters,
BaseModel? model,
CancelToken? cancelToken,
Options? options
})
2.3 上传图片|文件,Future请求方式,可以使用await阻塞同步返回结果,也可以使用then异步返回结果。
/// brief 上传图片 (通过Future方式请求,可以使用await阻塞直到获取到结果)
/// @param url 接口地址
/// @param filePath 图片地址
/// @param attachmentType 上传附件类型
/// @param customAttachmentType 上传附件类型 (attachmentType为custom时,取customAttachmentType的值, 若为空默认为"system")
/// @param fileName 图片名字
/// @param mime 图片格式
/// @param showProgress 是否显示上传进度
/// @param onSendProgress 发送文件进度回调
/// @param onReceiveProgress 接收文件进度回调
/// @param cancelToken 取消请求的token
/// @param options 对请求的设置
Future>uploadImage(String url, String filePath, AttachmentType attachmentType, {
String? customAttachmentType,
String? fileName,
String mime = 'png',
bool showProgress = false,
bool isShow = false, // 是否显示加载吐司
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
CancelToken? cancelToken,
Options? options
})
2.4 下载图片|文件,Future请求方式,可以使用await阻塞同步返回结果,也可以使用then异步返回结果。
/// brief 下载文件 (通过Future方式请求,可以使用await阻塞直到获取到结果)
/// @param uri 文件地址
/// @param savePath 文件保存地址
/// @param showProgress 是否显示下载进度
/// @param deleteOnError 下载失败后删除文件
/// @param onReceiveProgress 接收文件进度回调
/// @param cancelToken 取消请求的token
/// @param options 对请求的设置
FuturedownloadFile(Uri uri, String savePath, AttachmentType attachmentType, {
Map? data,
bool showProgress = false,
bool deleteOnError = true,
bool isShow = false, // 是否显示加载吐司
ProgressCallback? onReceiveProgress,
CancelToken? cancelToken,
Options? options
});
3、临时需要发起不同于主接口请求,但是又不想改变主服务器地址的,可以直接指定服务器接口地址,使用以下两个方法:
3.1 异步请求方式,采用异步回调的方式返回结果,数据直接在onSuccess、onSuccessList或者onPageSuccessList中获取。单个请求时可用这个方法,如果有多个请求互相依赖时使用这种方式会形成嵌套调用,就不推荐了。
/// brief http请求 (通过回调函数回调结果)
/// @param method 请求方式
/// @param url 接口地址
/// @param params post请求参数
/// @param queryParameters get请求参数
/// @param isShow 请求时是否显示吐司
/// @param isPageData 是否是分页数据
/// @param isList 是否是列表数据
/// @param model 要解析的数据模型
/// @param onSuccess 请求成功回调 (返回数据)
/// @param onSuccessList 请求成功回调 (返回列表数据)
/// @param onPageSuccessList 请求成功回调 (返回分页列表数据)
/// @param onError 请求失败回调
/// @param cancelToken 取消请求的token
/// @param options 对请求的设置
/// @param needDecrypt 是否需要对结果解密
/// @param secret 解密密钥
/// @param interceptors 要添加的拦截器
/// @param isJson 后台返回的结果是否是json字符串
void newAsyncRequestNetwork(String baseUrl, String path, Method method, {
dynamic params,
Map? queryParameters,
bool isShow = false, // 是否显示加载吐司
bool isPageData = false, // 是否是分页数据
bool isList = false,
BaseModel? model,
Function(T? t)? onSuccess,
Function(List list)? onSuccessList,
Function(List list, int total, int perPage, int currentPage)? onPageSuccessList,
Function(int code, String msg)? onError,
CancelToken? cancelToken,
Options? options,
bool needDecrypt = false,
String? secret,
List? interceptors,
int sendTimeout = 15,
int connectTimeout = 15,
int receiveTimeout = 15,
bool isJson = true
})
3.2 Future请求方式,可以使用await阻塞同步返回结果,也可以使用then异步返回结果。单个、多个都可以使用该方法,数据需要自己从返回值里面取一下。 特别适用于FutureBuilder构建的组建中。
/// brief http请求 (通过Future方式请求,可以使用await阻塞直到获取到结果)
/// @param method 请求方式
/// @param url 接口地址
/// @param isPageData 是否是分页数据
/// @param params post请求参数
/// @param queryParameters get请求参数
/// @param model 要解析的数据模型
/// @param cancelToken 取消请求的token
/// @param options 对请求的设置
/// @param needDecrypt 是否需要对结果解密
/// @param secret 解密密钥
/// @param interceptors 要添加的拦截器
/// @param isJson 后台返回的结果是否是json字符串
Future> newRequestNetwork(String baseUrl, String path, Method method, {
dynamic params,
Map? queryParameters,
bool isShow : false, // 是否显示加载吐司
bool isPageData : false, // 是否是分页数据
BaseModel? model,
CancelToken? cancelToken,
Options? options,
bool needDecrypt = false,
String? secret,
List? interceptors,
int sendTimeout = 15,
int connectTimeout = 15,
int receiveTimeout = 15,
bool isJson = true
})
4、核心实体抽象类 BaseModel
建议所有自定义模型都实现BaseModel的抽象方法,方便接口请求数据可以统一的转模型,提高数据模型的标准性
class TestModel implements BaseModel {
int _age;
String _sex;
TestModel.fromJson(dynamic json) {
_age = json["age"];
_sex = json["sex"];
}
@override
BaseModel fromJson(json) {
return TestModel.fromJson(json);
}
@override
Map toJson() {
var map = {};
map["age"] = _age;
map["sex"] = _sex;
return map;
}
}
// 使用如下,传入model,返回的就已经是传入的model类型的数据了
BaseEntity result = await DioHttp.requestNetwork(Method.get, Api.Symbol_List, queryParameters: params, model: TestModel());
if (result.code == 0 && null != result.data) {
Log.d(result.data!);
}