Dio 泛型网络请求封装。带基类。带完整日志输出
Posted 安果移不动
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dio 泛型网络请求封装。带基类。带完整日志输出相关的知识,希望对你有一定的参考价值。
import 'dart:convert' as convert;
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:anguo/utils/app_info_utlis.dart';
import 'package:anguo/utils/my_flutter_toast.dart';
import 'package:anguo/utils/net_work_tools.dart';
import 'package:anguo/utils/passport_manager.dart';
import 'package:anguo/utils/time_utils.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_ad/bean/base_bean.dart';
import 'package:flutter_ad/generated/json/base/json_convert_content.dart';
import 'package:flutter_ad/utils/key_utlis.dart';
class APIDio {
// 工厂模式
// late static Dio dio
static Dio? dio = null;
static const int CONNECT_TIMEOUT = 10000;
static const int RECEIVE_TIMEOUT = 10000;
static const String GET = 'get';
static const String POST = 'post';
static const String PUT = 'put';
static const String PATCH = 'patch';
static const String DELETE = 'delete';
static Dio createInstance() {
//仅仅初始化一次。
if (dio == null) {
//设置请求参数 基础配置
late int requestTime;
late int revicerTime;
int sRequestId = 0;
dio = Dio();
dio!.options = BaseOptions(
connectTimeout: CONNECT_TIMEOUT,
receiveTimeout: RECEIVE_TIMEOUT,
headers: getHeader());
//设置拦截器 打印日志等
dio!.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
Map<String, dynamic> header = getHeader();
requestTime = DateTime.now().millisecondsSinceEpoch;
sRequestId++;
return handler.next(options);
}, onResponse: (response, handler) async {
_printLog(response, sRequestId, requestTime);
var resDataList = convert.jsonDecode(response.data);
int code = resDataList['code'];
if (code == 0 || code == 1) {
return handler.next(response);
//-200 token失效
} else if (code == -200) {
//当出现错误 把 msg 打出来
ToastUtils.showToast("登录信息过期。请重新登录");
PassportManager.logout();
PassportManager.goLogin(KeyUtils.globalKey.currentState!.context)
.then((value) => null);
} else {
ToastUtils.showToast(resDataList['msg']);
return handler.reject(DioError(
error: resDataList['msg'],
requestOptions: response.requestOptions));
}
}, onError: (DioError e, handler) {
return handler.next(e);
}));
}
return dio!;
}
// https://blog.csdn.net/zhayunbiao/article/details/109361229 网络请求优化
static Future<void> _printLog(
Response response, int sRequestId, int requestTime) async {
int revicerTime = DateTime.now().millisecondsSinceEpoch;
// print('***************** ${response.requestOptions.uri} *****************');
// print('data: ${response.requestOptions.data}');
// printMoreLineLog(response.toString());
sRequestId++;
String inputContent = "网络日志:\\n" +
"--> sending request ${response.requestOptions.uri.toString()} \\n" +
"method: ${response.requestOptions.method}\\n" +
"sequence: ${sRequestId.toString()}\\n" +
"requestTime: ${TimeUtils.formatTimebYtimeMillis(requestTime, "yyyy-MM-dd HH:mm:ss SSS")}\\n" +
"params: ${response.requestOptions.queryParameters.toString()}\\n" +
"data: ${response.requestOptions.data.toString()}\\n" +
"header: \\n{\\n${response.requestOptions.headers.toString()}}\\n" +
"<--received response for ${response.requestOptions.uri.toString()}\\n" +
"sequence: ${sRequestId.toString()}\\n" +
"receivedTime: ${TimeUtils.formatTimebYtimeMillis(revicerTime, "yyyy-MM-dd HH:mm:ss SSS")}\\n" +
"duration: ${(revicerTime - requestTime).toString()}\\n" +
"response: ${response.toString()}\\n" +
"header: \\n{\\n${response.headers.map.toString()}\\n";
//直接运行
if (kDebugMode || kProfileMode) {
// LogUtil.d(inputContent);
//测试环境下打印日志
log(inputContent);
}
}
static getHeader() {
String? token = PassportManager.getUserInfo()?.accessToken;
return {
'Content-Type': 'application/x-www-form-urlencode',
'Authorization': token != null && token.length > 0 ? 'Bearer $token' : '',
'AppVersion': AppInfoUtils.getVersionName(),
'channel': 'app_${Platform.isandroid ? "android" : "ios"}',
};
}
static void _getResponse<T>({
required String url,
required String method,
parameters,
Function(T? t)? onSuccess,
Function(String error)? onError,
}) async {
// try {
Response response;
Dio dio = createInstance();
switch (method) {
case GET:
response = await dio.get(url, queryParameters: parameters);
break;
case PUT:
response = await dio.put(url, queryParameters: parameters);
break;
case PATCH:
response = await dio.patch(url, queryParameters: parameters);
break;
case DELETE:
response = await dio.delete(url, queryParameters: parameters);
break;
default:
response = await dio.post(url, data: parameters);
break;
}
/// 拦截http层异常码
if (response.statusCode == 200) {
/// 这里做baseBena泛型解析,封装 并拦截后台code异常码,可拦截自定义处理
Map<String, dynamic> jsonData = jsonDecode(response.data);
var bean = BaseBean<T>();
bean.msg = jsonData['msg'];
bean.code = jsonData['code'];
if (jsonData.containsKey("data")) {
bean.data = JsonConvert.fromJsonAsT(jsonData['data']);
}
if (response.statusCode == 200 && onSuccess != null) {
if (bean.code == 1) {
onSuccess(bean.data);
} else {
if (onError != null) {
//自定义网络请求错误
onError(bean.msg);
}
}
} else {
if (onError != null) {
onError(bean.msg);
}
}
} else {
throw Exception(
'statusCode:${response.statusCode}+${response.statusMessage}');
}
// } catch (e) {
// print('请求出错:' + e.toString());
// if (onError != null) {
// onError(e.toString());
// }
// }
}
static Future<dynamic> get<T>(
{required String url,
required parameters,
Function(T? t)? onSuccess,
Function(String error)? onError}) async {
NetWorkUtils.connectTips();
_getResponse<T>(
url: url,
method: GET,
parameters: parameters,
onSuccess: onSuccess,
onError: onError);
}
static Future<dynamic> post<T>(
{required String url,
required parameters,
Function(T? t)? onSuccess,
Function(String error)? onError}) async {
try {
NetWorkUtils.connectTips();
_getResponse<T>(
url: url,
method: POST,
parameters: parameters,
onSuccess: onSuccess,
onError: onError);
} on DioError catch (e) {
handleErr(e);
}
}
static void handleErr(DioError e) {
print(
"DioError:${e.requestOptions.uri} ${e.message}",
);
if (e.message == null || e.message.isEmpty) return;
throw '$e';
}
}
class BaseBean<T> {
late String msg;
late int code;
T? data;
}
实用范例
static Future homeAdList(int page,
{String? search, String? part, int? uid}) async {
Map<String, dynamic>? param = {};
if (uid != null) {
param['uid'] = uid;
}
if (search != null) {
param['search'] = uid;
}
param['page'] = page;
await APIDio.get<AdListEntity>(
url: APIConstant.list_ad,
parameters: param,
onSuccess: (AdListEntity? data) {
print("onSuccess---------");
print(data.adList.toString());
print(data.totalPage.toString());
print(data.currentPage.toString());
print("onSuccess---------");
},
onError: (msg) {
print("onError---------${msg}");
print(msg);
});
}
打印结果
I/flutter (18097): onSuccess---------
I/flutter (18097): [Instance of 'AdListAdList']
I/flutter (18097): 1
I/flutter (18097): 1
I/flutter (18097): onSuccess---------
以上是关于Dio 泛型网络请求封装。带基类。带完整日志输出的主要内容,如果未能解决你的问题,请参考以下文章
flutter dio网络请求封装经过多次修改更新 呕心沥血而成的封装版本 返回future 加入token的版本