注意flutter 的 rxdart 请求超时回调不在onError里面 需要在请求地方添加timeout,超时回调会在此处,如下图:
RequestMap.requestNotPayOrder(context)
.timeout(Duration(seconds: Utils.getConnectTime()), onTimeout: (sink) {
ShowLoadLoadingDialog.hideLoadingDialog();
}).listen((data) async {
ShowLoadLoadingDialog.hideLoadingDialog();
if (data?.data != null) {
if (data.data.appNoPwd) {
if (data.data.notPayNum == 0) {
String result =
await scanQrCodePlatform.invokeMethod('startCaptureActivity');
handleCaptureResult(result);
} else {
showDialogType = 1;
showDialog<Null>(
context: context, //BuildContext对象
barrierDismissible: true,
builder: (BuildContext context) {
return getCustomDialog();
});
}
} else {
ToastUtils.toastUtils(context, msg: S.of(context).mian_page_no_pwd);
}
}
}, onError: (err) {
ShowLoadLoadingDialog.hideLoadingDialog();
});
以上是原先的解决方案,不解耦,每个请求都需要写一个请求超时的回调,很不方便,所以在请求dio返回的future中做监听操作,如下所示,避免了在每个请求里面监听超时的操作:
/// 参数说明 url 请求路径
/// queryParamerers 是 请求参数
/// baseWidget和baseInnerWidgetState用于 加载loading 和 设置 取消CanselToken
/// isCancelable 是设置改请求是否 能被取消 , 必须建立在 传入baseWidget或者baseInnerWidgetState的基础之上
/// isShowLoading 设置是否能显示 加载loading , 同样要建立在传入 baseWidget或者 baseInnerWidgetState 基础之上
/// isShowErrorToaet 这个是 设置请求失败后 是否要 吐司的
PublishSubject<T> _requstHttp<T>(String url,
[bool isGet,
queryParameters,
BaseIntercept baseIntercept,
bool isCancelable,
bool isShowToast = true]) {
Future future;
PublishSubject<T> publishSubject = PublishSubject<T>();
CancelToken cancelToken;
_setInterceptOrcancelAble(baseIntercept, isCancelable, cancelToken);
Map<String, String> headers = Map<String, String>();
if (Utils.isString(SpUtil.getString(SharedPreferencesTag.SKEY))) {
headers['UCODE'] = SpUtil.getString(SharedPreferencesTag.SKEY);
_dio.options.headers = headers;
}
// _dio.options.queryParameters =
// queryParameters; //注意自定义baseOption会让下面的queryParameters失效,所以此处需要赋值给他
this.isShowToast = isShowToast;
if (isGet) {
_dio.options.connectTimeout = 2000; //2s
_dio.options.receiveTimeout = 1000;
} else {
_dio.options.connectTimeout = CONNECR_TIME_OUT; //5s
_dio.options.receiveTimeout = RECIVE_TIME_OUT;
}
if (isGet) {
future = _dio.get(url,
cancelToken: cancelToken, queryParameters: queryParameters);
} else {
future = _dio.post(url,
cancelToken: cancelToken,
queryParameters: queryParameters,
data: queryParameters);
}
LogUtil.e("api 请求: $url \nisGet$isGet params$queryParameters header" +
headers.toString());
future.then((data) {
//这里要做错误处理
//需要先过滤 error , 根据和后台的 约定 , 搞清楚什么是失败
// 什么是成功 , 这里只是根据了干货集中营的 返回 模拟了一下
LogUtil.e("data$data");
String code = json.decode(data.toString())["code"];
String msg = json.decode(data.toString())["msg"];
msg = msg == null || msg == "" ? S.of(mContext).request_fail : msg;
LogUtil.e("api ---responseData----\n"
"${data}"
"\n-----");
if (code != "0") {
callError(
publishSubject,
MyError(int.parse(code), msg),
baseIntercept,
);
} else {
//这里的解析 请参照 https://www.jianshu.com/p/e909f3f936d6 , dart的字符串 解析蛋碎一地
publishSubject
.add(EntityFactory.generateOBJ<T>(json.decode(data.toString())));
publishSubject.close();
cancelLoading(baseIntercept);
}
}, onError: (err) {
if (err is DioError) {
switch (err.type) {
case DioErrorType.CONNECT_TIMEOUT:
callError(
publishSubject,
MyError(NetTypeConfig.CONNECT_TIMEOUT,
S.of(mContext).net_connect_timeout),
baseIntercept);
break;
case DioErrorType.SEND_TIMEOUT:
callError(
publishSubject,
MyError(NetTypeConfig.SEND_TIMEOUT,
S.of(mContext).net_send_timeout),
baseIntercept);
break;
case DioErrorType.RECEIVE_TIMEOUT:
callError(
publishSubject,
MyError(NetTypeConfig.RECEIVE_TIMEOUT,
S.of(mContext).net_receive_timeout),
baseIntercept);
break;
case DioErrorType.RESPONSE:
callError(
publishSubject,
MyError(NetTypeConfig.RESPONSE, S.of(mContext).net_response),
baseIntercept);
break;
case DioErrorType.CANCEL:
callError(
publishSubject,
MyError(NetTypeConfig.CANCEL, S.of(mContext).net_cancel),
baseIntercept);
break;
case DioErrorType.DEFAULT:
callError(
publishSubject,
MyError(NetTypeConfig.DEFAULT, S.of(mContext).net_defult),
baseIntercept);
break;
}
}
}).catchError((err) {
LogUtil.e("catchError${err.toString()}");
callError(publishSubject, MyError(-1000, S.of(mContext).request_error),
baseIntercept);
});
return publishSubject;
}