记录学习flutter开发中的探索,借鉴了网上很多大佬的思路,如有雷同,那大概率是我抄的(手动狗头)。
此系列仅为记录个人学习中的思路。
文中所用环境及配置
flutter 2.2.3
dio 4.0.0
logger 1.1.0 #log输出
目录结构
大概封装内容
-
token校验
-
log输出
-
异常处理
......
开始封装
http单例操作类:http_client.dart
这里仅写了get和post
class HttpClient {
Dio _dio;
//定义一个共用的取消令牌,可用于用户操作时token校验失败取消其他请求操作
CancelToken cancelToken = CancelToken();
static HttpClient _instance = HttpClient._internal();
HttpClient._internal() {
//请求头,依需求自己添加对应内容
Map<String, dynamic> header = {};
if (null == _dio) {
_dio = Dio(
BaseOptions(
contentType: 'application/json',
connectTimeout: 10000,
receiveTimeout: 10000,
sendTimeout: 10000,
headers: header,
),
);
_dio.interceptors.add(MyHttpInterceptor());
}
}
///使用单例模式创建
static HttpClient getInstance({String baseUrl}) {
if (baseUrl == null) {
return _instance._normal();
} else {
return _instance._otherDomain(baseUrl);
}
}
///用于指定域名
///因项目暂时没用到,所以先不做此方面的处理
HttpClient _otherDomain(String baseUrl) {
if (_dio != null) {
_dio.options.baseUrl = baseUrl;
}
return this;
}
///返回默认域名
HttpClient _normal() {
if (_dio != null) {
if (_dio.options.baseUrl != NetWorkAddress.baseUrl) {
_dio.options.baseUrl = NetWorkAddress.baseUrl;
}
}
return this;
}
Future<BaseResponse> get({
String url,
Map<String, dynamic> params,
Map<String, dynamic> data,
CancelToken cancelToken,
ProgressCallback onReceiveProgress,
}) async {
try {
Response response = await _dio.get(
url,
queryParameters: params,
cancelToken: cancelToken ?? this.cancelToken,
onReceiveProgress: onReceiveProgress,
);
return handleResponse(response, cancelToken: cancelToken ?? this.cancelToken);
} on Exception catch (e) {
return handleException(e, cancelToken: cancelToken ?? this.cancelToken);
}
}
Future<BaseResponse> post({
String url,
Map<String, dynamic> params,
Map<String, dynamic> data,
CancelToken cancelToken,
ProgressCallback onReceiveProgress,
}) async {
try {
Response response = await _dio.post(
url,
queryParameters: params,
cancelToken: cancelToken ?? this.cancelToken,
onReceiveProgress: onReceiveProgress,
);
return handleResponse(response, cancelToken: cancelToken ?? this.cancelToken);
} on Exception catch (e) {
return handleException(e, cancelToken: cancelToken ?? this.cancelToken);
}
}
}
自定义拦截器: http_interceptor.dart
此处仅进行了log输出,未作其他处理
class MyHttpInterceptor extends InterceptorsWrapper {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
super.onRequest(options, handler);
logger.i("----------请求---------\nurl: ${options.uri.toString()}\n"
"headers: ${options.headers}\nmethod: ${options.method}\nparams: ${options.queryParameters}\n"
"data: ${options.data}");
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
super.onResponse(response, handler);
//此处因为直接打印response的话,所输出的json串会无引号,所以添加一下转换
var json = jsonEncode(response.data);
logger.i("----------返回---------\nurl: ${response.requestOptions.uri}\n"
"code: ${response.statusCode}\nmessage: ${response.statusMessage}\ndata: $json");
}
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
super.onError(err, handler);
logger.e("----------错误---------\ntype: ${err.type}\nmessage: ${err.message}");
}
}
返回结果处理:http_response.dart
BaseResponse handleResponse(Response response, {CancelToken cancelToken,}) {
// 返回值异常
if (response.statusCode != 200)
return handleException(
HttpException(response.statusMessage, response.statusCode),
cancelToken: cancelToken,
);
return BaseResponse(
code: response.statusCode,
message: response.statusMessage,
data: response.data,
);
}
///处理异常
BaseResponse handleException(Exception exception, {CancelToken cancelToken,}) {
HttpException _parseException;
if (exception is HttpException) _parseException = exception;
else _parseException = parseException(exception);
//在这里可进行异常处理
logger.e("----------异常处理---------\n${_parseException.toString()}");
return BaseResponse(code: _parseException.code, message: _parseException.message);
}
///解析异常
HttpException parseException(Exception exception) {
if (exception is DioError) {
switch (exception.type) {
case DioErrorType.connectTimeout:
return HttpException("连接超时,请重试");
case DioErrorType.sendTimeout:
return HttpException("请求超时,请稍后重试");
case DioErrorType.receiveTimeout:
return HttpException("请求失败,请稍后重试");
case DioErrorType.cancel: //请求被取消
return HttpException(exception.message);
case DioErrorType.response:
try {
int code = exception.response?.statusCode;
switch (code) {
case 401:
return HttpException("登录失效", code);
case 500:
return HttpException(exception.response?.statusMessage, 500);
case 400:
default:
return HttpException(exception.response?.statusMessage, code);
}
} on Exception catch (_) {
return HttpException(exception.response.statusMessage);
}
return HttpException(exception.response.statusMessage);
default: //未知异常
return HttpException(exception.message, exception.hashCode);
}
} else {
return HttpException(exception.toString());
}
}
返回的数据类型:response_model.dart
class BaseResponse<T>{
int code;
String message;
T data;
BaseResponse({this.code,this.message,this.data});
@override
String toString() {
return "code: $code\nmessage: $message\ndata: $data";
}
}
自定义的异常,方便后期学到新知识扩展:http_exception.dart
class HttpException implements Exception{
final String _message;
String get message => _message ?? this.runtimeType.toString();
final int _code;
int get code => _code ?? -1;
HttpException([this._message, this._code]);
String toString() {
return "code: $code\nmessage: $message";
}
}
使用
var response = HttpClient.getInstance().get(url: NetWorkAddress.userInfo,);
到此封装结束。
最后
在写下这篇时,仍然查阅了许多前辈写的dio封装文章,收获颇多,这篇文章属实是小巫见大巫,纯粹是个人学习的记录(因为经常看过就忘记。。。),有什么写得不对的地方,大佬们请见谅~