Flutter网络请求dio简易封装
2022-04-22 本文已影响0人
禄子_c79b
DioManager
/// date : 2021/7/11
/// desc : 网络请求类
///成功回调
typedef Success<T> = Function(T? data);
///失败回调,若传空,则系统吐司提示,若不会空,自行处理错误结果
typedef Fail = Function(int? code, String? msg);
class DioManager {
/// 默认code--返回成功
static const RESP_OK = 200;
/// 默认code--40001未登录,40002token失效,40010账号被异地登录,40011token来源异常
static const List RESP_LOGIN_EXPIRE = [40001, 40002, 40010, 40011];
String? signKey;
Dio dio = new Dio();
static DioManager? _instance;
static DioManager getInstance() {
if (_instance == null) {
_instance = new DioManager();
_instance!._init();
}
return _instance!;
}
void _init() {
dio.options.baseUrl = "https://www.fastmock.site/mock/6d5084df89b4c7a49b28052a0f51c29a/test/";
dio.options.connectTimeout = 5000;
dio.options.receiveTimeout = 5000;
dio.options.responseType = ResponseType.json;
dio.interceptors.add(HeaderInterceptor()); //请求头拦截器
dio.interceptors.add(DioLogInterceptor()); //是否开启请求日志
// dio.interceptors.add(ResponseInterceptor()); //请求结果回调
}
void setBaseUrl(String baseUrl) {
dio.options.baseUrl = baseUrl;
}
void setSignKey(String signKey) => this.signKey = signKey;
void setHeader(Map<String, dynamic>? headers) {
dio.options.headers = headers;
}
///post form 表单提交操作
Future postForm<T>(
String path, {
SplayTreeMap<String, dynamic>? params,
required Success<T> success,
required Fail? fail,
bool withLoading = true,
}) async {
var splayTreeMap = new SplayTreeMap<String, dynamic>();
if (params != null) {
splayTreeMap.addAll(params);
}
if (withLoading) {
// ToastUtils.getInstance().showLoading();
}
try {
var response = await dio.post(path, data: FormData.fromMap(splayTreeMap));
parseResponse(response, success, fail);
} on DioError catch (e) {
formatError(e, fail);
}
}
///post json
Future postJson<T>(
String path, {
SplayTreeMap<String, dynamic>? params,
required Success<T> success,
required Fail? fail,
bool withLoading = true,
}) async {
var splayTreeMap = new SplayTreeMap<String, dynamic>();
if (params != null) {
splayTreeMap.addAll(params);
}
if (withLoading) {
// ToastUtils.getInstance().showLoading();
}
try {
var response = await dio.post(path, data: splayTreeMap);
parseResponse(response, success, fail);
print('你好============response11${response}');
} on DioError catch (e) {
formatError(e, fail);
}
}
///get
Future get<T>(
String path, {
SplayTreeMap<String, dynamic>? params,
required Success<T> success,
required Fail? fail,
bool withLoading = true,
}) async {
var splayTreeMap = new SplayTreeMap<String, dynamic>();
if (params != null) {
splayTreeMap.addAll(params);
}
if (withLoading) {
// ToastUtils.getInstance().showLoading();
}
try {
var response = await dio.get(path, queryParameters: splayTreeMap);
parseResponse(response, success, fail);
} on DioError catch (e) {
formatError(e, fail);
}
}
void parseResponse<T>(
Response<dynamic> response, Success<T> success, Fail? fail) {
// ToastUtils.getInstance().hideLoading();
if (response.statusCode == 200) {
Map<String, dynamic> result = response.data;
if (result["code"] == RESP_OK) {
success(result["data"]);
return;
}
if (RESP_LOGIN_EXPIRE.contains(result["code"])) {
//登录过期需要重新登录
// ToastUtils.getInstance().toastFail(result["msg"]);
// NativeUtils.sendNativeData(NativeUtils.NATIVE_LOGIN);
return;
}
if (fail != null) {
// fail(result["code"], result["msg"]);
fail(result["code"], result["message"]);
} else {
// ToastUtils.getInstance().toastFail(result["msg"] ?? '');
}
} else {
if (fail != null) {
fail(response.statusCode ?? -1, response.statusMessage ?? 'error');
} else {
// ToastUtils.getInstance().toastFail(response.statusMessage ?? 'error');
}
}
}
void formatError(DioError e, Fail? fail) {
print(e.stackTrace);
if (fail != null) {
fail(-1, e.message);
} else {
// ToastUtils.getInstance().toastFail(e.message);
}
}
}
HeaderInterceptor
/// author : luzi
/// date : 2021/7/11
/// desc : 请求头拦截器
class HeaderInterceptor extends Interceptor {
@override
Future<void> onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
Map<String, dynamic> headers = options.headers;
headers['clientId'] = 1; //渠道(1.APP 2.Web)
if (Platform.isAndroid) {
headers['systemName'] = 'Android'; //系统名称
} else if (Platform.isIOS) {
headers['systemName'] = 'iOS'; //系统名称
}
var time = DateTime.now().millisecondsSinceEpoch;
headers['ts'] = time; //时间戳
String sign = getParamsStr(options, time);
headers['sign'] = sign; //参数加密签名
headers['language'] = Get.locale?.countryCode ?? 'MY'; //语言环境
headers['Accept'] = 'application/json';
options.headers = headers;
handler.next(options);
}
getParamsStr(RequestOptions options, int time) {
StringBuffer stringBuffer = new StringBuffer();
String? paramsStr;
var method = options.method;
if (method == 'GET') {
if (options.queryParameters.isNotEmpty) {
String query = options.uri.query;
var splitArray = query.split('&');
var splayTreeMap = new SplayTreeMap();
splitArray.forEach((split) {
var splitChild = split.split('=');
splayTreeMap[splitChild[0]] = Uri.encodeQueryComponent(splitChild[1]);
});
paramsStr = json.encode(splayTreeMap);
if (paramsStr.isNotEmpty) {
stringBuffer.write('$paramsStr&');
} else {
stringBuffer.write('{}&');
}
} else {
stringBuffer.write('{}&');
}
} else if (method == 'POST') {
var data = options.data;
if (data is FormData) {
if (data.fields.isNotEmpty) {
String replace = data.fields
.join(",")
.replaceAll('MapEntry', '')
.replaceAll('(', '')
.replaceAll(')', '');
paramsStr = replace;
if (paramsStr.isNotEmpty) {
stringBuffer.write('{$paramsStr}&');
} else {
stringBuffer.write('{}&');
}
} else {
stringBuffer.write('{}&');
}
} else {
paramsStr = jsonEncode(data);
if (paramsStr.isNotEmpty) {
stringBuffer.write('$paramsStr&');
} else {
stringBuffer.write('{}&');
}
}
}
// NativeUtils.sendNativeData(NativeUtils.NATIVE_LOG, paramsStr.toString());
// print(paramsStr.toString());
stringBuffer.write('ts=$time&');
stringBuffer.write('tmpsign=${DioManager.getInstance().signKey}');
String toString = stringBuffer.toString().replaceAll("\"", "");
// NativeUtils.sendNativeData(NativeUtils.NATIVE_LOG, toString);
// print(toString);
// Get.log.printInfo(info: '拼接后:$toString');
var content = new Utf8Encoder().convert(toString);
var digest = md5.convert(content);
String md5Encode = hex.encode(digest.bytes).toUpperCase();
Get.log.printInfo(info: 'MD5:$md5Encode');
return md5Encode;
}
}
DioLogInterceptor
/// date : 2021/7/11
/// desc : 日志拦截器
class DioLogInterceptor extends Interceptor {
/// Print request [Options]
final bool request;
/// Print request header [Options.headers]
final bool requestHeader;
/// Print request data [Options.data]
final bool requestBody;
/// Print [Response.data]
final bool responseBody;
/// Print [Response.headers]
final bool responseHeader;
/// Print error message
final bool error;
/// InitialTab count to logPrint json response
static const int initialTab = 1;
/// 1 tab length
static const String tabStep = ' ';
/// Print compact json response
final bool compact;
/// Width size per logPrint
final int maxWidth;
/// Log printer; defaults logPrint log to console.
/// In flutter, you'd better use debugPrint.
/// you can also write log in a file.
void Function(Object object) logPrint;
DioLogInterceptor({
this.request = true,
this.requestHeader = true,
this.requestBody = true,
this.responseHeader = false,
this.responseBody = true,
this.error = true,
this.maxWidth = 90,
this.compact = true,
this.logPrint = print,
});
@override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
if (request) {
_printRequestHeader(options);
}
if (requestHeader) {
_printMapAsTable(options.queryParameters, header: 'Query Parameters');
final requestHeaders = Map();
requestHeaders.addAll(options.headers);
requestHeaders['contentType'] = options.contentType?.toString();
requestHeaders['responseType'] = options.responseType.toString();
requestHeaders['followRedirects'] = options.followRedirects;
requestHeaders['connectTimeout'] = options.connectTimeout;
requestHeaders['receiveTimeout'] = options.receiveTimeout;
_printMapAsTable(requestHeaders, header: 'Headers');
_printMapAsTable(options.extra, header: 'Extras');
}
if (requestBody && options.method != 'GET') {
final data = options.data;
if (data != null) {
if (data is Map) _printMapAsTable(options.data, header: 'Body');
if (data is FormData) {
final formDataMap = Map()
..addEntries(data.fields)
..addEntries(data.files);
_printMapAsTable(formDataMap, header: 'Form data | ${data.boundary}');
} else
_printBlock(data.toString());
}
}
handler.next(options);
}
@override
void onError(
DioError err,
ErrorInterceptorHandler handler,
) async {
if (error) {
if (err.type == DioErrorType.response) {
final uri = err.response?.requestOptions.uri;
_printBoxed(
header:
'DioError ║ Status: ${err.response?.statusCode} ${err.response?.statusMessage}',
text: uri.toString());
if (err.response != null && err.response?.data != null) {
logPrint('╔ ${err.type.toString()}');
if (err.response != null) {
_printResponse(err.response!);
}
}
_printLine('╚');
logPrint('');
} else
_printBoxed(header: 'DioError ║ ${err.type}', text: err.message);
}
handler.next(err);
}
@override
void onResponse(
Response response,
ResponseInterceptorHandler handler,
) async {
if (responseHeader) {
final responseHeaders = Map<String, String>();
response.headers
.forEach((k, list) => responseHeaders[k] = list.toString());
_printMapAsTable(responseHeaders, header: 'Headers');
}
if (responseBody) {
_printResponseHeader(response);
logPrint('╔ Body');
logPrint('║');
_printResponse(response);
logPrint('║');
_printLine('╚');
}
handler.next(response);
}
void _printBoxed({String? header, String? text}) {
logPrint('');
logPrint('╔╣ $header');
logPrint('║ $text');
_printLine('╚');
}
void _printResponse(Response response) {
if (response.data != null) {
if (response.data is Map)
_printPrettyMap(response.data);
else if (response.data is List) {
logPrint('║${_indent()}[');
_printList(response.data);
logPrint('║${_indent()}[');
} else
_printBlock(response.data.toString());
}
}
void _printResponseHeader(Response? response) {
final uri = response?.requestOptions.uri;
final method = response?.requestOptions.method;
//添加以下代码,防止多接口请求时 response的header和body被分开打印
String header =
'Response ║ $method ║ Status: ${response?.statusCode} ${response?.statusMessage}';
logPrint('╔╣ $header' + ('═' * 70));
logPrint('║ ${uri.toString()}');
logPrint('║ ');
}
void _printRequestHeader(RequestOptions? options) {
final uri = options?.uri;
final method = options?.method;
_printBoxed(header: 'Request ║ $method ', text: uri.toString());
}
void _printLine([String pre = '', String suf = '╝']) =>
logPrint('$pre${'═' * maxWidth}$suf');
void _printKV(String key, Object? v) {
final pre = '╟ $key: ';
final msg = v.toString();
if (pre.length + msg.length > maxWidth) {
logPrint(pre);
_printBlock(msg);
} else
logPrint('$pre$msg');
}
void _printBlock(String msg) {
int lines = (msg.length / maxWidth).ceil();
for (int i = 0; i < lines; ++i) {
logPrint((i >= 0 ? '║ ' : '') +
msg.substring(i * maxWidth,
math.min<int>(i * maxWidth + maxWidth, msg.length)));
}
}
String _indent([int tabCount = initialTab]) => tabStep * tabCount;
void _printPrettyMap(Map data,
{int tabs = initialTab, bool isListItem = false, bool isLast = false}) {
final bool isRoot = tabs == initialTab;
final initialIndent = _indent(tabs);
tabs++;
if (isRoot || isListItem) logPrint('║$initialIndent{');
data.keys.toList().asMap().forEach((index, key) {
final isLast = index == data.length - 1;
var value = data[key];
// key = '\"$key\"';
if (value is String) value = '\"$value\"';
if (value is Map) {
if (compact && _canFlattenMap(value))
logPrint('║${_indent(tabs)} $key: $value${!isLast ? ',' : ''}');
else {
logPrint('║${_indent(tabs)} $key: {');
_printPrettyMap(value, tabs: tabs);
}
} else if (value is List) {
if (compact && _canFlattenList(value))
logPrint('║${_indent(tabs)} $key: ${value.toString()}');
else {
logPrint('║${_indent(tabs)} $key: [');
_printList(value, tabs: tabs);
logPrint('║${_indent(tabs)} ]${isLast ? '' : ','}');
}
} else {
final msg = value.toString().replaceAll('\n', '');
final indent = _indent(tabs);
final linWidth = maxWidth - indent.length;
if (msg.length + indent.length > linWidth) {
int lines = (msg.length / linWidth).ceil();
for (int i = 0; i < lines; ++i) {
logPrint(
'║${_indent(tabs)} ${msg.substring(i * linWidth, math.min<int>(i * linWidth + linWidth, msg.length))}');
}
} else
logPrint('║${_indent(tabs)} $key: $msg${!isLast ? ',' : ''}');
}
});
logPrint('║$initialIndent}${isListItem && !isLast ? ',' : ''}');
}
void _printList(List list, {int tabs = initialTab}) {
list.asMap().forEach((i, e) {
final isLast = i == list.length - 1;
if (e is Map) {
if (compact && _canFlattenMap(e))
logPrint('║${_indent(tabs)} $e${!isLast ? ',' : ''}');
else
_printPrettyMap(e, tabs: tabs + 1, isListItem: true, isLast: isLast);
} else
logPrint('║${_indent(tabs + 2)} $e${isLast ? '' : ','}');
});
}
bool _canFlattenMap(Map map) {
return map.values.where((val) => val is Map || val is List).isEmpty &&
map.toString().length < maxWidth;
}
bool _canFlattenList(List list) {
return (list.length < 10 && list.toString().length < maxWidth);
}
void _printMapAsTable(Map? map, {String? header}) {
if (map == null || map.isEmpty) return;
logPrint('╔ $header ');
map.forEach((key, value) => _printKV(key, value));
_printLine('╚');
}
}
OperatingCenterEngine
class OperatingCenterEngine {
static Future queryAlertInfo(Success<Map<String, dynamic>> success,
{Fail? fail}) async {
await DioManager.getInstance().get('warning-rules/getConfiguration',
params: null, success: success, fail: fail);
}
static Future updateAlertInfo(
String alertAmount, Success<Map<String, dynamic>> success,
{Fail? fail}) async {
SplayTreeMap<String, dynamic> map = new SplayTreeMap<String, dynamic>();
map['alertAmount'] = alertAmount;
await DioManager.getInstance().postJson(
'warning-rules/alertValueConfiguration',
params: map,
success: success,
fail: fail);
}
static Future queryBindBankInfo(Success<Map<String, dynamic>> success,
{Fail? fail}) async {
await DioManager.getInstance().postJson('bank-card/cashDetail',
params: null, success: success, fail: fail);
}
static Future addExample(
SplayTreeMap<String, dynamic> map, Success<Map<String, dynamic>> success,
{Fail? fail}) async {
await DioManager.getInstance()
.postJson('bank-card/save', params: map, success: success, fail: fail);
}
static Future updateExample(
SplayTreeMap<String, dynamic> map, Success<Map<String, dynamic>> success,
{Fail? fail}) async {
await DioManager.getInstance().postJson('bank-card/update',
params: map, success: success, fail: fail);
}
static Future getExampleList(Success<List<dynamic>> success,
{Fail? fail}) async {
SplayTreeMap<String, dynamic> map = new SplayTreeMap();
map['dictCode'] = 'CASH_BANK';
await DioManager.getInstance()
.get('dict/listDictValue', params: map, success: success, fail: fail);
}
static Future getImageCodeNew( SplayTreeMap<String, dynamic> map,Success<Map<String, dynamic>> success,
{Fail? fail}) async {
// SplayTreeMap<String, dynamic> map = new SplayTreeMap();
// map['ceshi'] = '123456999999';
await DioManager.getInstance()
.postJson('test', params: map, success: success, fail: fail);
}
}
实际调用
SplayTreeMap<String, dynamic> map = new SplayTreeMap();
map['username'] ="你好" ;
map['loongwind'] ="123456" ;
OperatingCenterEngine.getImageCodeNew(map,(data) =>{
print('你好============123456${data!['age']}'),
});