直接上代码,好用点赞,不好用你喷我
拦截器,给head添加token;拦截401相关
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:yzm_flutter_driver/base/services/auth_service.dart';
import 'package:get/get.dart' as getx;
import 'package:yzm_flutter_driver/network/network_interceptor/repository.dart';
import '../../common/utils/toast.dart';
import '../../routes/app_pages.dart';
import '../base_model/result_base.dart';
/// 请求拦截相关的处理
class NetInterceptor extends Interceptor {
NetInterceptor();
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
if (!options.headers.containsKey("token")) {
final token = AuthService.to.token;
if (token != null && token.isNotEmpty) {
options.headers['token'] = token;
}
}
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
int? statusCode = response.statusCode;
if (statusCode == 200) {
Map dataMap;
if (response.data != null) {
if (response.data is Map<String, dynamic>) {
dataMap = response.data as Map;
} else if (response.data is String) {
dataMap = jsonDecode(response.data) as Map;
} else {
dataMap = {'code': 200, 'data': response.data, 'message': 'success'};
}
final result = wrapResult(dataMap as Map<String, dynamic>);
}
}
handler.next(response);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
return handler.next(err);
}
}
// 首先,你需要定义一个函数来根据数据类型将解析后的数据包装为 Result 对象:
Result<T> wrapResult<T>(Map<String, dynamic> dataMap) {
return Result<T>(
code: dataMap['code'],
info: dataMap['info'],
data: dataMap['data'], // Adjust this based on your data structure
);
}
import 'package:dio/dio.dart';
import 'package:yzm_flutter_driver/common/utils/app_log.dart';
/// 统一处理错误信息
String formatError(e) {
if (e is Response) {
logger.d(e.toString());
return e.statusMessage ?? '请求错误';
}
if (e is DioException) {
String message = "";
if (e.response != null && e.response!.statusCode != null) {
switch (e.response!.statusCode) {
case 400:
message = "请求参数有误"; // signature Attestation of failure
break;
case 403:
message = "请求被拒绝";
break;
case 404:
message = "资源未找到";
break;
case 405:
message = "请求方式不被允许";
break;
case 408:
message = "请检查网络是否可用,再行尝试"; // 请求超时
break;
case 422:
message = "请求语义错误";
break;
case 500:
message = "服务器逻辑错误";
break;
case 502:
message = "服务器网关错误";
break;
case 504:
message = "服务器网关超时";
break;
default:
message = "请求异常,请稍后再试";
}
return message;
} else {
switch (e.type) {
case DioExceptionType.connectionTimeout:
message = "连接超时";
break;
case DioExceptionType.sendTimeout:
message = "请求超时";
break;
case DioExceptionType.receiveTimeout:
message = "响应超时";
break;
case DioExceptionType.connectionError:
message = "当前网络不可用,请检查你的网络...";
break;
default:
if (e.message != null && e.message!.isNotEmpty) {
message = e.message!;
} else {
message = "请求异常";
}
break;
}
return message;
}
} else if (e is TypeError) {
return "数据解析类型转换异常";
}
return "未知错误";
}
网络请求封装
import 'package:json_annotation/json_annotation.dart';
@JsonSerializable()
class Result<T> {
@JsonKey(name: 'code')
int code;
@JsonKey(name: 'msg')
String? info;
@JsonKey(name: 'data')
dynamic data;
Result({
required this.code,
required this.info,
required this.data,
});
factory Result.fromJson(Map<String, dynamic> json) {
return Result(
code: json['code'] as int,
info: json['msg'] == null ? '' : json['msg'] as String,
data: json['data'] as dynamic,
);
}
Map<String, dynamic> toJson() {
return {
'code': code,
'msg': info,
'data': data,
};
}
}
class YzmError {
late int errorCode;
late String errorMsg;
}
class ApiClient {
late Dio _dio;
String baseUrl = BaseConstants.BASE_URL;
// 私有构造函数
ApiClient._internal() {
_dio = Dio(BaseOptions(
sendTimeout: const Duration(seconds: 10),
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 10)))
..interceptors.addAll([
LogInterceptor(
requestBody: true,
responseBody: true,
),
NetInterceptor(),
]); // 创建Dio实例
}
static final ApiClient _instance = ApiClient._internal();
// 工厂方法返回单例实例
factory ApiClient() {
return _instance;
}
/// POST请求
Future<void> postRequest(
{required String url,
required Map<String, dynamic> request,
required Function(Result) reqeustSuccess,
required Function(YzmError) requestFail,
Map<String, dynamic> headers = const <String, dynamic>{}}) async {
const extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final data = <String, dynamic>{};
data.addAll(request);
Result value = Result(code: 0, info: "info", data: Map());
try {
final result = await _dio
.fetch<Map<String, dynamic>>(_setStreamType<Result<String>>(Options(
method: 'POST',
headers: headers,
extra: extra,
)
.compose(
_dio.options,
url,
queryParameters: queryParameters,
data: json.encode(data),
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
))));
_requestInfo(value, result, reqeustSuccess, requestFail);
} catch (e) {
// e= 网络错误,解析数据异常,其它
YzmError error = YzmError();
error.errorCode = 0;
error.errorMsg = formatError(e);
requestFail(error);
return;
}
}
/// url合并
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}
final url = Uri.parse(baseUrl);
if (url.isAbsolute) {
return url.toString();
}
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
}
/// dio的参数解析
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||
requestOptions.responseType == ResponseType.stream)) {
if (T == String) {
requestOptions.responseType = ResponseType.plain;
} else {
requestOptions.responseType = ResponseType.json;
}
}
return requestOptions;
}
YzmError _requestError(Result value) {
YzmError error = YzmError();
error.errorCode = value.code;
error.errorMsg = value.info ?? "";
return error;
}
// 网络请求返回信息通用
_requestInfo(
value,
result,
Function(Result) reqeustSuccess,
Function(YzmError) requestFail,
) {
// 网络请求错误相关异常
if (result.statusCode != 200) {
YzmError error = YzmError();
error.errorCode = 0;
DioException dioException =
DioException(requestOptions: result.requestOptions, response: result);
error.errorMsg = formatError(dioException);
requestFail(error);
return;
}
// 解析数据
value = Result.fromJson(result.data!);
// 返回的业务异常
if (value.code != 200) {
requestFail(_requestError(value));
return;
}
// 返回成功
reqeustSuccess(value);
}
}
class ApiUrl {
static const String getsxxxx= "/system/xxx/xxx";
}
使用
chooseRole(String type) async {
Toast.showLoading();
Map<String, dynamic> request = {};
request['xx'] = type;
await ApiClient().postRequest(
url: ApiUrl.xxx,
request: request,
reqeustSuccess: (result) {
Toast.hideLoading();
},
requestFail: (a) {
Toast.hideLoading();
BotToast.showText(text: a.errorMsg);
},
);
}