当前位置:   article > 正文

flutter封装dio请求库,让我们做前端的同学可以轻松上手使用,仿照axios的使用封装_flutter dio封装

flutter dio封装

dio是一个非常强大的网络请求库,可以支持发送各种网络请求,就像axios一样灵活强大,但是官网没有做一个demo示例,所以前端同学使用起来还是有点费劲,所以就想在这里封装一下,方便前端同学使用。

官网地址:dio | Dart Package

我的flutter模板项目地址: GitHub - Sjj1024/flutter_windows: 使用flutter开发跨平台桌面软件的案例

添加依赖

在pubspec.yaml文件中添加所需要的第三方依赖库

  1. dependencies:
  2. flutter:
  3. sdk: flutter
  4. # The following adds the Cupertino Icons font to your application.
  5. # Use with the CupertinoIcons class for iOS style icons.
  6. cupertino_icons: ^1.0.2
  7. get: ^4.6.6
  8. dio: ^5.4.0

封装基础请求工具

在utils里面新建一个request.dart文件,专门用来做请求工具的,就像前端框架里面集成axios一样:统一初始化网络请求常见配置,实现请求拦截器、响应拦截器以及错误处理。

request.dart 代码: 

  1. import 'package:dio/dio.dart';
  2. /// 请求方法:枚举类型
  3. enum DioMethod {
  4. get,
  5. post,
  6. put,
  7. delete,
  8. patch,
  9. head,
  10. }
  11. // 创建请求类:封装dio
  12. class Request {
  13. /// 单例模式
  14. static Request? _instance;
  15. // 工厂函数:执行初始化
  16. factory Request() => _instance ?? Request._internal();
  17. // 获取实例对象时,如果有实例对象就返回,没有就初始化
  18. static Request? get instance => _instance ?? Request._internal();
  19. /// Dio实例
  20. static Dio _dio = Dio();
  21. /// 初始化
  22. Request._internal() {
  23. // 初始化基本选项
  24. BaseOptions options = BaseOptions(
  25. baseUrl: 'http://你的服务器地址',
  26. connectTimeout: const Duration(seconds: 5),
  27. receiveTimeout: const Duration(seconds: 5));
  28. _instance = this;
  29. // 初始化dio
  30. _dio = Dio(options);
  31. // 添加拦截器
  32. _dio.interceptors.add(InterceptorsWrapper(
  33. onRequest: _onRequest, onResponse: _onResponse, onError: _onError));
  34. }
  35. /// 请求拦截器
  36. void _onRequest(RequestOptions options, RequestInterceptorHandler handler) {
  37. // 对非open的接口的请求参数全部增加userId
  38. if (!options.path.contains("open")) {
  39. options.queryParameters["userId"] = "xxx";
  40. }
  41. // 头部添加token
  42. // options.headers["token"] = "xxx";
  43. // 更多业务需求
  44. handler.next(options);
  45. // super.onRequest(options, handler);
  46. }
  47. /// 相应拦截器
  48. void _onResponse(
  49. Response response, ResponseInterceptorHandler handler) async {
  50. // 请求成功是对数据做基本处理
  51. if (response.statusCode == 200) {
  52. // 处理成功的响应
  53. // print("响应结果: $response");
  54. } else {
  55. // 处理异常结果
  56. print("响应异常: $response");
  57. }
  58. handler.next(response);
  59. }
  60. /// 错误处理: 网络错误等
  61. void _onError(DioException error, ErrorInterceptorHandler handler) {
  62. handler.next(error);
  63. }
  64. /// 请求类:支持异步请求操作
  65. Future<T> request<T>(
  66. String path, {
  67. DioMethod method = DioMethod.get,
  68. Map<String, dynamic>? params,
  69. dynamic data,
  70. CancelToken? cancelToken,
  71. Options? options,
  72. ProgressCallback? onSendProgress,
  73. ProgressCallback? onReceiveProgress,
  74. }) async {
  75. const _methodValues = {
  76. DioMethod.get: 'get',
  77. DioMethod.post: 'post',
  78. DioMethod.put: 'put',
  79. DioMethod.delete: 'delete',
  80. DioMethod.patch: 'patch',
  81. DioMethod.head: 'head'
  82. };
  83. // 默认配置选项
  84. options ??= Options(method: _methodValues[method]);
  85. try {
  86. Response response;
  87. // 开始发送请求
  88. response = await _dio.request(path,
  89. data: data,
  90. queryParameters: params,
  91. cancelToken: cancelToken,
  92. options: options,
  93. onSendProgress: onSendProgress,
  94. onReceiveProgress: onReceiveProgress);
  95. return response.data;
  96. } on DioException catch (e) {
  97. print("发送请求异常: $e");
  98. rethrow;
  99. }
  100. }
  101. /// 开启日志打印
  102. /// 需要打印日志的接口在接口请求前 Request.instance?.openLog();
  103. void openLog() {
  104. _dio.interceptors
  105. .add(LogInterceptor(responseHeader: false, responseBody: true));
  106. }
  107. }

管理apis网络请求

然后创建一个apis文件夹,集成所有的apis网络请求,并在里面创建user.dart、goods.dart等文件,用于对不同的网络请求进行管理,这样就可以知道我们相关的网路请求放在哪里面。并且对返回的数据根据实际需求进行处理,如果数据的修改需要更新UI或者需要全局共享该数据

app.dart文件代码:

  1. import '../utils/request.dart';
  2. // 创建一个关于user相关请求的对象
  3. class UserApi {
  4. /// 单例模式
  5. static UserApi? _instance;
  6. // 工厂函数:初始化,默认会返回唯一的实例
  7. factory UserApi() => _instance ?? UserApi._internal();
  8. // 用户Api实例:当访问UserApi的时候,就相当于使用了get方法来获取实例对象,如果_instance存在就返回_instance,不存在就初始化
  9. static UserApi? get instance => _instance ?? UserApi._internal();
  10. /// 初始化
  11. UserApi._internal() {
  12. // 初始化基本选项
  13. }
  14. /// 获取权限列表
  15. getUser() async {
  16. /// 开启日志打印
  17. Request.instance?.openLog();
  18. /// 发起网络接口请求
  19. var result = await Request().request('get_user', method: DioMethod.get);
  20. // 返回数据
  21. return result.data;
  22. }
  23. // 获取列表数据
  24. getGoods() async {
  25. var result = await Request().request("/game/gamemgnt",
  26. method: DioMethod.post,
  27. data: {"taskuuid": "queryprod", "splist": "66"});
  28. // 返回数据
  29. // print("getDetail:$result");
  30. return result;
  31. }
  32. // 获取列表数据
  33. getDetail() async {
  34. var result = await Request().request("/game/gamemgnt",
  35. method: DioMethod.post,
  36. data: {"taskuuid": "queryprod", "splist": "66"});
  37. // 返回数据
  38. // print("getDetail:$result");
  39. return result;
  40. }
  41. }
  42. // 导出全局使用这一个实例
  43. final userApi = UserApi();

在组件页面使用

然后就可以到组件页面导入userApi给组件页面上使用,发送相应的网络请求了:

页面组件导入并发送请求获取数据,然后渲染:

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_windows/apis/app.dart';
  3. class Lists extends StatefulWidget {
  4. const Lists({super.key});
  5. @override
  6. State<Lists> createState() => _ListsState();
  7. }
  8. class _ListsState extends State<Lists> {
  9. // 列表数据
  10. List goods = [];
  11. @override
  12. void initState() {
  13. // TODO: implement initState
  14. super.initState();
  15. // 获取商品列表
  16. getGoods();
  17. }
  18. // 获取列表
  19. getGoods() async {
  20. var res = await userApi.getGoods();
  21. var goodsData = res['response_data']['data'];
  22. setState(() {
  23. goods = goodsData;
  24. });
  25. }
  26. // 动态列表组件
  27. List<Widget> _getListData() {
  28. var tempList = goods.map((value) {
  29. return Container(
  30. decoration: BoxDecoration(
  31. border: Border.all(
  32. color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)),
  33. child: Column(
  34. children: <Widget>[
  35. Image.network(
  36. value['skillurl'],
  37. width: 100,
  38. height: 200,
  39. ),
  40. const SizedBox(height: 12),
  41. Text(
  42. value['pordname'],
  43. textAlign: TextAlign.center,
  44. style: const TextStyle(fontSize: 20),
  45. )
  46. ],
  47. ),
  48. );
  49. }); // ('xxx','xxx')
  50. print("渲染的列表组件类型:${tempList.toList().runtimeType}");
  51. return tempList.toList();
  52. }
  53. @override
  54. Widget build(BuildContext context) {
  55. return Scaffold(
  56. appBar: AppBar(
  57. title: Text("产品列表"),
  58. ),
  59. body: GridView.count(
  60. crossAxisSpacing: 10.0,
  61. //水平子 Widget 之间间距
  62. mainAxisSpacing: 10.0,
  63. //垂直子 Widget 之间间距
  64. padding: const EdgeInsets.all(2),
  65. crossAxisCount: 4,
  66. //一行的 Widget 数量
  67. // childAspectRatio: 0.7,
  68. //宽度和高度的比例
  69. children: goods.map((value) {
  70. return Container(
  71. decoration: BoxDecoration(
  72. border: Border.all(
  73. color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)),
  74. child: Column(
  75. children: <Widget>[
  76. Image.network(
  77. value['skillurl'],
  78. width: 100,
  79. height: 200,
  80. ),
  81. const SizedBox(height: 12),
  82. Text(
  83. value['pordname'],
  84. textAlign: TextAlign.center,
  85. style: const TextStyle(fontSize: 20),
  86. )
  87. ],
  88. ),
  89. );
  90. }).toList(),
  91. ),
  92. );
  93. }
  94. }

 最后展示的效果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/596892
推荐阅读
相关标签
  

闽ICP备14008679号