启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
Flutter系列文章列表
- 2022年了,你还不会flutter!!!
- Flutter 第一课---flutter特点及组件开发
- Flutter 第二课---组件生命周期和App生命周期
- Flutter 第三课---状态管理之Provide
- Flutter 第四课---路由管理
- Flutter 第五课 --- 包管理器和资源管理
- Flutter 第六课 --- flutter网络请求
为什么需要封装Dio?
在上一节课中,我们对比了三种网络请求的方式,发现Dio已经足够易用,之所以有想法去封装是想让请求流程更加统一,比如load、错误请求以及成功、失败情况下统一处理,传入参数可能会比较多,导致方法看起来会很臃肿。所以自己进行了封装和改善。而且封装代码有如下优点:
- 统一请求流程
- 统一响应处理,200情况下的api不同情况的处理
- 统一ERROR处理
- 针对拦截器、缓存、统一处理错误等多个配置进行统一管理
对Dio请求进行初始化
首先对连结超时时间 、响应超时时间 、BaseUrl 进行统一设置
import 'package:dio/dio.dart';
class Request {
// 配置 Dio 实例
static final BaseOptions _options = BaseOptions(
baseUrl: 'https://test.com',
connectTimeout: 10000, // 连接超时时间
receiveTimeout: 10000, // 响应超时时间
);
// 声明Dio变量
Dio dio;
// 初始化dio
Dio dio = Dio(BaseOptions);
}
创建(GET、POST、PUT、DELETE)方法
class Request {
static Future<T> get<T>(String path, {params}) {
return _request(path, method: 'get', queryParameters: params);
}
static Future<T> post<T>(String path, {params, data}) {
return _request(path, method: 'post', queryParameters: params, data: data);
}
static Future<T> delete<T>(String path, {params, data}) {
return _request(path, method: 'delete', queryParameters: params);
}
static Future<T> put<T>(String path, {params, data}) {
return _request(path, method: 'put', queryParameters: params, data: data);
}
}
Restful APi封装
因为不管是get()还是post()请求,Dio 内部最终都会调用request 方法,_request 是核心函数,所有的请求都会走这里。
// _request 是核心函数,所有的请求都会走这里
static Future<T> _request<T>(String path, {required String method, queryParameters, data}) async {
if (queryParameters != null) {
var params = '';
queryParameters.forEach((key, value) {
if (!path.contains(key)) {
params += key + '=' + value.toString() + '&';
}
});
var url = params.substring(0, params.length - 1);
path += '?$url';
print(path);
}
try {
Response response = await _dio.request(path, data: data, options: Options(method: method));
if (response.statusCode == 200 || response.statusCode == 201) {
if (response.data is Map) {
return response.data;
} else {
return json.decode(response.data.toString());
}
} else {
EasyLoading.dismiss();
return Future.error('HTTP错误');
}
} on DioError catch (e) {
EasyLoading.dismiss();
print("错误状态码${e.response?.statusCode},错误消息${e.response?.statusMessage}");
}
return Future.error('HTTP错误');
}
至此一个最基本的网络请求就完成了,如何调用,我们只需要在用到网络请求的组件中,调用类对应的请求方式即可,如下是一个用户名登录流程
// (1) 导入Restful api
import '../utils/dio_request.dart';
// (2) 封住用户登录api
class UserLogin {
static getUserLogin(name) {
return Request.get(
'/user/wq',
params: {},
);
}
}
// 用户名登录流程
userNameLogin() async {
String username = _controller.text;
EasyLoading.show(status: 'loading...');
var result = await UserLogin.getUserLogin(username);
print("拿到用户信息")
}
封装拦截器
在开发的过程中,需要在请求前、响应前、错误时对某一些接口做特殊的处理,那我们就需要用到拦截器。这时候需要创建一个继承Interceptor的接口:
import 'package:dio/dio.dart';
import 'package:flutter_dio/dio_util/dio_response.dart';
class DioInterceptors extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
// 头部添加token
options.headers["token"] = "xxx";
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
// 请求成功是对数据做基本处理
if (response.statusCode == 200) {
response.data = DioResponse(code: 0, message: "请求成功啦", data: response);
} else {
response.data = DioResponse(code: 1, message: "请求失败啦", data: response);
}
}
}
如上是对请求前增加token以及请求成功失败的错误处理。更多详情配置清查阅dio官方文档
结束语
关于flutter网络封装的学习到这里就结束了。下期我们来说说flutter原生转web的学习。如果你刚好正在学习flutter,可以关注我,请相信会给你不一样的收获。如果你是flutter大佬,欢迎指导!