创建HTTP_CONFIG文件

/lib/utils/http/http_config.dart

此文件用来设置BaseOptions dio的公共配置文件!

1
2
3
4
5
class HTTPConfig {
// static const baseURL = "https://api.oioweb.cn";
static const baseURL = "http://5d85ccfb1e61af001471bf60.mockapi.io";
static const timeout = 60 * 1000;
}

baseURL: api 接口地址! 例如: http://5d85ccfb1e61af001471bf60.mockapi.io/user

timeout: 超时时间! 响应超时, 请求超时等...

创建HTTP核心文件

/lib/utils/http/http.dart

此文件用来初始化dio实例, 并配置request请求方法,以及interceptor拦截器相关配置!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:rent_house/utils/http/interceptor.dart';
import './http_config.dart';

class HTTPRequest {
static final BaseOptions options = BaseOptions(
baseUrl: HTTPConfig.baseURL,
// 连接超时
connectTimeout: const Duration(milliseconds: HTTPConfig.timeout),
// 响应超时
receiveTimeout: const Duration(milliseconds: HTTPConfig.timeout));

static Dio dio = Dio(options);

static Future request(
String url, {
String method = "get",
data,
Map<String, dynamic>? params,
Options? customOptions,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
// 1请求的单独配置
Options options = customOptions ?? Options(method: method);

// 2 添加一个拦截器
/* Interceptor inter = InterceptorsWrapper(
onRequest: (options, handler) {
// 很多页面访问必须要求携带token 那么可以在这里判断是否有token
// 权限验证:比如接口请求后端返回401未授权时可以跳到登录页,403跳到未授权页面;
// 异常监控:可以在拦截器处理异常,并且上报到异常监控后台或者发送异常预警消息;
// 缓存接口:可以对于某些接口将请求缓存在本地,设定一定的缓存有效时限,在时限内重复请求时直接返回本地缓存数据,而无需请求后端接口,降低后端服务器负荷。这块可以参考

print(options.baseUrl);
print(options.path);
print(options.uri);
print("拦截了请求");
return handler.next(options);
},
onResponse: (e, handler) {
print(e);
print("拦截了响应");

return handler.next(e);
},
onError: (e, handler) {
print(e);
print("拦截了错误");
return handler.next(e);
},
); */

List<Interceptor> inters = [];

// inters.add(inter);
// 添加自己定义的授权拦截器
inters.add(AuthInterCeptor());
// 开启一个log 拦截器
// 此拦截器将帮助您在发出 HTTP 请求和响应的同时创建所有日志。您将能够看到您请求的所有信息。
/**
* uri: https://api.oioweb.cn/api/qq/vip?qq=1023954998
* statusCode: 200
* headers:
* access-control-allow-headers: X-Requested-With
* connection: keep-alive
* access-control-allow-origin: *
* date: Sun, 09 Apr 2023 06:30:44 GMT
* access-control-allow-methods: GET,POST,OPTIONS
* content-encoding: gzip
* content-length: 563
* strict-transport-security: max-age=31536000
* content-type: application/json;charset=utf-8
* server: Tengine
*
* */
inters.add(LogInterceptor(responseHeader: false, responseBody: true));

dio.interceptors.addAll(inters);
// 3 发起网络请求
try {
Response response = await dio.request(url,
data: data,
queryParameters: params,
options: options,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress);
// print(response.data);
return response.data;
} on DioException catch (e) {
print('戳错了?????????? ${e.toString()}');
// Fluttertoast.showToast(msg: 'Error');
EasyLoading.showError(e.toString(),
duration: const Duration(milliseconds: 1500),
maskType: EasyLoadingMaskType.black);
// print(e);
return Future.error(e);
}
}
}

创建自定义拦截器

/lib/utils/http/interceptor.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get_core/get_core.dart';
import 'package:get/get_navigation/src/extension_navigation.dart';
// 自定义一个拦截器
import 'package:dio/dio.dart';

import '../../router/app_pages.dart';

class AuthInterCeptor extends Interceptor {
AuthInterCeptor();

// 请求拦截器
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
// 这里你可以创建一个path 列表,标记处不需要access_token的路径
final listPath = ["/login", "/resgiter", "/sendMsgCode", "/api/qq/vip"];
// 进行判断 是否需要追加token
if (listPath.contains(options.path)) {
print("/api/qq/vip");
// 不需要token 直接返回
return handler.next(options);
}

// 这里从本地读取自己的token 拼接上去
String access_token = "access_token";
options.headers.addAll({'Authorization': access_token});
return handler.next(options);
}

// 响应拦截器
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
if (response.statusCode == 401) {
EasyLoading.showToast(
'token is invalid or expired! Please try again later!',
duration: const Duration(seconds: 3));

Get.toNamed(Routes.LOGIN);
}
super.onResponse(response, handler);
}

@override
void onError(DioException err, ErrorInterceptorHandler handler) {
EasyLoading.showError(err.message as String);
super.onError(err, handler);
}
}

api模块封装

新建/lib/api/user.dart模块

1
2
3
4
5
6
7
8
9
10
11
import '../../utils/http/http.dart';
// import 'package:dio/dio.dart';

class UserAPI {
static Future getUserList({Map<String, dynamic>? params}) {
return HTTPRequest.request('/user');
/* return await Dio()
.request('http://5d85ccfb1e61af001471bf60.mockapi.io/user'); */
}
}

场景应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 获取用户列表
Future<List<String>> Function(String filter) asyncItems =
(String filter) async {
try {
var userList = await UserAPI.getUserList(params: {"filter": filter});

List<UserModel>? models = UserModel.fromJsonList(userList);

// List<String> a = models.map(item => item.name);
List<String> UserNameList = models!.map((e) => e.name).toList();
// print('models $UserNameList');
return UserNameList;
} catch (e) {
print('报错了~~~~ $e');
return [];
}
};