结合前端开发经验,对Dio进行封装。
不是很必要,拦截处理下就行。
主要实现以下功能:
- 请求拦截,添加统一请求头
- 封装get、post
- response解析
- response异常处理
- token过期处理(结合eventBus)
实现代码如下:
创建文件 customHttp.dart
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'CustomEvent.dart';
import 'SharedPreferencesService.dart';
import 'constants.dart';
final options = BaseOptions(
baseUrl: Constants.serverAddress,//远程服务器地址,即请求前缀
connectTimeout: const Duration(seconds: 12),
receiveTimeout: const Duration(seconds: 12),
);
final dio = Dio(options);
class CustomInterceptor extends Interceptor{
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
// print("拦截");
try{
//请求头添加token
String? token = SharedPreferencesService.instance.getString("token");
if(token!=null)options.headers["token"]=token;
}catch(e){
print(e);
}
// print('REQUEST[${options.method}] => PATH: ${options.path}');
super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
if (kDebugMode) {
print('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
}
super.onResponse(response, handler);
}
/*@override
void onError(DioError err, ErrorInterceptorHandler handler) async{
if (kDebugMode) {
print('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
}
super.onError(err, handler);
}*/
}
class DioApi{
static get(String path, {
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
}) async{
try{
dynamic response = await dio.get(path,
queryParameters:queryParameters,
options: options
);
return _handleResponse(response);
}on DioError catch(e){
return _handleException(e);
}
}
static post(String path, {
data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async{
try{
dynamic response = await dio.post(path,
data:data,
queryParameters:queryParameters,
options: options
);
return _handleResponse(response);
}on DioError catch(e){
return _handleException(e);
}
}
static dynamic _handleResponse(Response<dynamic> response){
Map<String,dynamic> res =jsonDecode(response.toString());
return res;
}
static dynamic _handleException(e) async{
//异常响应
String msg = e.message??"message为空";
int code;
if (e.response != null) {
code = e.response.data["code"];
if(e.response.data["code"]==401){
msg = "登录已过期,请重新登录";
final prefs = SharedPreferencesService.instance;
await prefs.remove("token");
}
} else {
code = 500;
}
// 格式保持和后端返回一致,或自行封装定义
late Map<String, dynamic> response;
response = e.response?.data ?? {
"code": code,
"msg": msg,
};
if(code==401) {
response={
"code":code,
"msg":msg,
};
//token过期,触发过期事件
eventBus.fire(TokenExpireEvent());
}
return response;
}
}
使用
import 'package:dio/dio.dart';
import 'customHttp.dart';
void main() async {
// add interceptors
dio.interceptors.add(LogInterceptor());
dio.interceptors.add(CustomInterceptor());
}
token过期监听
在入口页面加入监听代码
// 事件监听
Future.delayed(Duration.zero,(){
eventBus.on<TokenExpireEvent>().listen((event) {
// All events are of type TokenExpireEvent (or subtypes of it).
try{
context.pushReplacement("/login");
}catch(e){
if (kDebugMode) {
print(e);
}
}
});
});