使用dio插件获取首页网络数据
- 安装dio插件:
-
pubspec.yaml文件中,安装方式如下
-
- 发送请求获取网络数据
class _HomePageState extends State<HomePage> {
@override
void initState() {
_loadData();
super.initState();
}
// 发送网络请求 获取首页网络数据
void _loadData() async {
// 1.准备请求地址
String path = 'http://xxxx.com/home/index';
// 2.创建http client
Dio dio = Dio();
// 3.发送请求并获取响应
try {
Response response = await dio.get(path);
print(response.data);
} catch (e) {
// 4.捕获异常
print(e);
}
}
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: const Text(
'首页',
style: TextStyle(fontSize: 20.0),
),
);
}
}
封装网络请求单例类
为什么要封装网络请求单例类
一个类只允许创建一个实例,那这个类就是一个单例类。这种设计模式就叫做单例设计模式,简称单例模式。
- 节省资源:
- 一个Dio实例就可以发起多个http请求,所以工程中可以只需要一个Dio实例
- 全局的配置信息
- 超时时间、baseUrl等等
- 全局的请求头信息
- 访问后端接口时,请求头中都需要传入用户身份和客户端类型信息
- 统一的异常处理
- 用户身份信息过期的处理等等
封装网络请求单例类实现和测试
实现request.dart
// 网络请求单例类
import 'package:dio/dio.dart';
class ZJYRequestManager {
// 声明dio
Dio? dio;
// 1. 私有的静态属性
static ZJYRequestManager? _instance;
// 2. 私有的命名构造函数:用于实例化单例类
ZJYRequestManager._initManager() {
// 需要在构造函数里面创建Dio实例
if (dio == null) {
// 设置全局配置信息
BaseOptions baseOptions = BaseOptions(
connectTimeout: 15000,
receiveTimeout: 5000,
baseUrl: 'http://xxx.com/',
);
dio = Dio(baseOptions);
// 使用dio拦截器
dio!.interceptors.add(InterceptorsWrapper(
onRequest: (
RequestOptions options,
RequestInterceptorHandler handler,
) {
// 发送请求前的拦截操作
// 如果需要在发送请求前补充一些额外的逻辑,代码这里写
// 设置全局请求头信息
options.headers = {
'Authorization': '', // 用户身份信息(登录之后才有)
'source-client': 'app', // 客户端类型
};
return handler.next(options);
},
onResponse: (
Response e,
ResponseInterceptorHandler handler,
) {
// 接收响应前的拦截操作
// 如果需要在接收响应前补充一些额外的逻辑,代码这里写(过滤数据)
return handler.next(e);
},
onError: (
DioError e,
ErrorInterceptorHandler handler,
) {
// 捕获到异常时的拦截操作
// 统一的异常处理
return handler.next(e);
},
));
}
}
// 3. 创建单例对象 并向外界提供单例对象的方法(工厂构造函数)
factory ZJYRequestManager() {
// 判断单例对象是否存在 如果不存在 新建 反之 直接返回单例对象
if (_instance == null) {
_instance = ZJYRequestManager._initManager();
}
return _instance!;
}
}
测试home.dart
class _HomePageState extends State<HomePage> {
@override
void initState() {
_loadData();
super.initState();
}
// 发送网络请求 获取首页网络数据
void _loadData() async {
// 发送请求并获取响应
try {
// 设置全局配置信息之后 发送请求
Response response = await ZJYRequestManager().dio!.get('home/index');
print(response.data);
} catch (e) {
// 4.捕获异常
print(e);
}
}
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: const Text(
'首页',
style: TextStyle(fontSize: 20.0),
),
);
}
}
封装处理请求的公共方法
为什么要封装处理请求的公共方法?
- 我们在使用dio插件封装单例类时,需要降低单例类和dio插件的耦合度
- 而且尽量不要对外暴露单例类内部的Dio实例
- 通过封装处理请求的公共方法,可以将单例类和dio插件解耦,而且对外也不会暴露Dio实例
如何封装处理请求的公共方法?
- 使用dio插件提供的request()方法封装处理请求的公共方法
- dio插件提供的request()方法是发送请求的底层方法,可以发送任何类型的请求
- 通过对request()方法的封装,我们也可以为单例类封装出一个发送任何类型请求的方法
实现
request.dart
...
// 处理请求的公共方法
Future<Response> handleRequest(
String path,
String method, {
data,
Map<String, dynamic>? queryParameters
}) {
return _dio!.request(
path,
data: data,
queryParameters: queryParameters,
options: Options(method: method),
);
}
使用
home.dart
...
// 发送网络请求 获取首页网络数据
void _loadData() async {
try {
// 使用处理请求的公共方法发送请求
Response response = await XTXRequestManager().handleRequest('home/index', 'GET');
print(response.data);
} catch (e) {
// 4.捕获异常
print(e);
}
}
...
使用网络请求单例类封装首页接口方法
为什么要封装接口方法?
- 有些接口可能会被访问多次,比如获取短信验证码的接口
- 所以为了能够实现接口复用和统一维护,我们还需要封装对应的接口方法
如何封装接口方法?
home_api.dart
class HomeAPI {
// 获取首页数据
static Future<Response> homeFetch() {
return XTXRequestManager().handleRequest('home/index', 'GET');
}
}
使用接口方法
home.dart
...
try {
// 使用首页接口方法 发送请求
Response response = await HomeAPI.homeFetch();
print(response.data);
} catch (e) {
// 4.捕获异常
print(e);
}
...