作者:Oo输不掉的气质 | 来源:互联网 | 2023-10-11 21:27
Flutter对Dio的封装以及注意事项-基本使用能够的两种方式回调使用方式NetUtil.instance.fetchUser(UserSettingService.appM
基本使用能够的两种方式
回调使用方式
NetUtil.instance.fetchUser(UserSettingService.appMenu, successCallback: (res) {
Log.i("resPayData === $res");
var result = AppMenuResponse.fromJson(res);
}, errorTypeCallback: (value) {
Log.i("resPayData === $value");
});
同步使用方式
var resPayCode =
await NetUtil.instance.fetchUser(UserSettingService.payCode);
Log.i("resPayData === $resPayCode");
var payCodeRespOnse= PayCodeResponse.fromJson(resPayCode);
_updateUi(payCodeResponse);
代码实现
import 'dart:convert';
import 'dart:io';
import 'package:bilibili_flutter/common/constant/bl_constant.dart';
import 'package:bilibili_flutter/common/log/bl_log.dart';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'dart:convert' as convert;
typedef ErrorTypeCallback = void Function();
typedef SuccessCallback = void Function(dynamic);
class NetUtil {
NetUtil._private();
factory NetUtil() {
return _instance ??= NetUtil._private();
}
static NetUtil? _instance;
static NetUtil _getInstance() {
_instance ??= NetUtil._private();
return _instance!;
}
static get instance => _getInstance();
getCurrentTimeMillis() {
return DateTime.now().millisecondsSinceEpoch;
}
final _dio = Dio(BaseOptions(
connectTimeout: 5000,
receiveTimeout: 5000,
));
Future fetchUser(
String path, {
Map paramData = const {},
SuccessCallback? successCallback,
ErrorTypeCallback? errorTypeCallback,
}) async {
return await fetchData("${GlobalConstant.host}$path",
param: paramData,
successCallback: successCallback,
errorTypeCallback: errorTypeCallback);
}
Future fetchData(
String url, {
Map param = const {},
SuccessCallback? successCallback,
ErrorTypeCallback? errorTypeCallback,
}) async {
try {
(_dio.httpClientAdapter as DefaultHttpClientAdapter).OnHttpClientCreate=
(client) {
client.badCertificateCallback = (cert, host, port) {
Log.i("host === $host");
Log.i("port === $port");
Log.i("sha1 === ${cert.sha1}");
Log.i("issuer === ${cert.issuer}");
Log.i("pem === ${cert.pem}");
return true;
};
};
Log.i("被调用了一次");
Log.i("url == $url");
var jsOnParam= {};
param.forEach((key, value) {
jsonParam[key] = value;
});
jsonParam["ts"] = getCurrentTimeMillis();
_dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
_dio.lock();
options.headers.remove("Content-Type");
var headerParam = {
"Connection": "true",
"os": _getPlatformName(),
"lang": "zh-cn",
"ENCRYPT": "1",
"Content-Type": "application/x-www-form-urlencoded"
};
// headerParam["token"] = token;
options.headers.addAll(headerParam);
_dio.unlock();
//请求数据前拦截
handler.next(options);
}, onResponse: (response, handler) {
//响应数据拦截
Log.i("onResponse:x === $response y ==== $handler");
handler.next(response); //保证链路关联上,不然请求不会被调用。
}, onError: (error, handler) {
//异常数据拦截
Log.i("onError:x === $error y ==== $handler");
handler.next(error);
}));
var requestParam = convert.jsonEncode(jsonParam);
Log.i("请求参数未加密:$requestParam");
// var encodeParam = aesEncode(requestParam, encryptKey, aesIv);
// Log.i("请求参数已加密:$encodeParam");
// var respOnse=
// await _dio.post(url, data: "post_data=$encodeParam");
var respOnse= await _dio.post(url, data: "post_data=");
if (response.statusCode == 200) {
Log.i("response statusCode == ${response.statusCode}");
Log.i("response data == ${response.data}");
var resCOntent=response.data ?? "";
""; //aesDecode(response.data ?? "", encryptKey, aesIv);
var resValue = json.decode(resContent);
successCallback?.call(resValue);
// Log.i("解密数据:$resContent");
return resValue;
} else {
//TODO 其他异常进行对应提示
errorTypeCallback?.call();
}
} catch (e) {
Log.i("发送了错误 === $e");
errorTypeCallback?.call();
}
}
/**
* 定义私有的获取平台的类型
*/
String _getPlatformName() {
if (Platform.isAndroid) {
return "Android";
} else if (Platform.isIOS) {
return "ios";
} else {
return "OtherOS";
}
}
}
注意事项
1. 添加拦截器后,需要对链进行手动调用,这里猜想应该是用到了设计模式中责任链模式。
_dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
_dio.lock();
options.headers.remove("Content-Type");
var headerParam = {
"Connection": "true",
// "csrf": csrf,
"os": _getPlatformName(),
"lang": "zh-cn",
"ENCRYPT": "1",
"Content-Type": "application/x-www-form-urlencoded"
};
// headerParam["token"] = token;
options.headers.addAll(headerParam);
_dio.unlock();///这里需要加锁哦。
//请求数据前拦截
handler.next(options);///这里需要手动调用next,不然事件流中的其他注册事件不会执行。
}, onResponse: (response, handler) {
//响应数据拦截
Log.i("onResponse:x === $response y ==== $handler");
handler.next(response); //保证链路关联上,不然请求不会被调用。
}, onError: (error, handler) {
//异常数据拦截
Log.i("onError:x === $error y ==== $handler");
handler.next(error);///这里需要手动调用next,不然事件流中的其他注册事件不会执行。
}));
2. 对https证书校验进行验证
(_dio.httpClientAdapter as DefaultHttpClientAdapter).OnHttpClientCreate=
(client) {
client.badCertificateCallback = (cert, host, port) {
Log.i("host === $host");
Log.i("port === $port");
Log.i("sha1 === ${cert.sha1}");
Log.i("issuer === ${cert.issuer}");
Log.i("pem === ${cert.pem}");
return true;///这里如果发挥false的话,那么请求将会终端。
};
};
源码地址
https://github.com/HaiYangCode/BilibiliFlutter/blob/main/lib/common/net/bl_net.dart