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

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

官网地址:dio | Dart Package

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

添加依赖

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

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  get: ^4.6.6
  dio: ^5.4.0

封装基础请求工具

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

request.dart 代码: 

import 'package:dio/dio.dart';

/// 请求方法:枚举类型
enum DioMethod {
  get,
  post,
  put,
  delete,
  patch,
  head,
}

// 创建请求类:封装dio
class Request {
  /// 单例模式
  static Request? _instance;

  // 工厂函数:执行初始化
  factory Request() => _instance ?? Request._internal();

  // 获取实例对象时,如果有实例对象就返回,没有就初始化
  static Request? get instance => _instance ?? Request._internal();

  /// Dio实例
  static Dio _dio = Dio();

  /// 初始化
  Request._internal() {
    // 初始化基本选项
    BaseOptions options = BaseOptions(
        baseUrl: 'http://你的服务器地址',
        connectTimeout: const Duration(seconds: 5),
        receiveTimeout: const Duration(seconds: 5));
    _instance = this;
    // 初始化dio
    _dio = Dio(options);
    // 添加拦截器
    _dio.interceptors.add(InterceptorsWrapper(
        onRequest: _onRequest, onResponse: _onResponse, onError: _onError));
  }

  /// 请求拦截器
  void _onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // 对非open的接口的请求参数全部增加userId
    if (!options.path.contains("open")) {
      options.queryParameters["userId"] = "xxx";
    }
    // 头部添加token
    // options.headers["token"] = "xxx";
    // 更多业务需求
    handler.next(options);
    // super.onRequest(options, handler);
  }

  /// 相应拦截器
  void _onResponse(
      Response response, ResponseInterceptorHandler handler) async {
    // 请求成功是对数据做基本处理
    if (response.statusCode == 200) {
      // 处理成功的响应
      // print("响应结果: $response");
    } else {
      // 处理异常结果
      print("响应异常: $response");
    }
    handler.next(response);
  }

  /// 错误处理: 网络错误等
  void _onError(DioException error, ErrorInterceptorHandler handler) {
    handler.next(error);
  }

  /// 请求类:支持异步请求操作
  Future<T> request<T>(
    String path, {
    DioMethod method = DioMethod.get,
    Map<String, dynamic>? params,
    dynamic data,
    CancelToken? cancelToken,
    Options? options,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    const _methodValues = {
      DioMethod.get: 'get',
      DioMethod.post: 'post',
      DioMethod.put: 'put',
      DioMethod.delete: 'delete',
      DioMethod.patch: 'patch',
      DioMethod.head: 'head'
    };
    // 默认配置选项
    options ??= Options(method: _methodValues[method]);
    try {
      Response response;
      // 开始发送请求
      response = await _dio.request(path,
          data: data,
          queryParameters: params,
          cancelToken: cancelToken,
          options: options,
          onSendProgress: onSendProgress,
          onReceiveProgress: onReceiveProgress);
      return response.data;
    } on DioException catch (e) {
      print("发送请求异常: $e");
      rethrow;
    }
  }

  /// 开启日志打印
  /// 需要打印日志的接口在接口请求前 Request.instance?.openLog();
  void openLog() {
    _dio.interceptors
        .add(LogInterceptor(responseHeader: false, responseBody: true));
  }
}

管理apis网络请求

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

app.dart文件代码:

import '../utils/request.dart';

// 创建一个关于user相关请求的对象
class UserApi {
  /// 单例模式
  static UserApi? _instance;

  // 工厂函数:初始化,默认会返回唯一的实例
  factory UserApi() => _instance ?? UserApi._internal();

  // 用户Api实例:当访问UserApi的时候,就相当于使用了get方法来获取实例对象,如果_instance存在就返回_instance,不存在就初始化
  static UserApi? get instance => _instance ?? UserApi._internal();

  /// 初始化
  UserApi._internal() {
    // 初始化基本选项
  }

  /// 获取权限列表
  getUser() async {
    /// 开启日志打印
    Request.instance?.openLog();

    /// 发起网络接口请求
    var result = await Request().request('get_user', method: DioMethod.get);

    // 返回数据
    return result.data;
  }

  // 获取列表数据
  getGoods() async {
    var result = await Request().request("/game/gamemgnt",
        method: DioMethod.post,
        data: {"taskuuid": "queryprod", "splist": "66"});
    // 返回数据
    // print("getDetail:$result");
    return result;
  }

  // 获取列表数据
  getDetail() async {
    var result = await Request().request("/game/gamemgnt",
        method: DioMethod.post,
        data: {"taskuuid": "queryprod", "splist": "66"});
    // 返回数据
    // print("getDetail:$result");
    return result;
  }
}

// 导出全局使用这一个实例
final userApi = UserApi();

在组件页面使用

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

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

import 'package:flutter/material.dart';
import 'package:flutter_windows/apis/app.dart';

class Lists extends StatefulWidget {
  const Lists({super.key});

  @override
  State<Lists> createState() => _ListsState();
}

class _ListsState extends State<Lists> {
  // 列表数据
  List goods = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    // 获取商品列表
    getGoods();
  }

  // 获取列表
  getGoods() async {
    var res = await userApi.getGoods();
    var goodsData = res['response_data']['data'];
    setState(() {
      goods = goodsData;
    });
  }

  // 动态列表组件
  List<Widget> _getListData() {
    var tempList = goods.map((value) {
      return Container(
        decoration: BoxDecoration(
            border: Border.all(
                color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)),
        child: Column(
          children: <Widget>[
            Image.network(
              value['skillurl'],
              width: 100,
              height: 200,
            ),
            const SizedBox(height: 12),
            Text(
              value['pordname'],
              textAlign: TextAlign.center,
              style: const TextStyle(fontSize: 20),
            )
          ],
        ),
      );
    }); // ('xxx','xxx')
    print("渲染的列表组件类型:${tempList.toList().runtimeType}");
    return tempList.toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("产品列表"),
      ),
      body: GridView.count(
        crossAxisSpacing: 10.0,
        //水平子 Widget 之间间距
        mainAxisSpacing: 10.0,
        //垂直子 Widget 之间间距
        padding: const EdgeInsets.all(2),
        crossAxisCount: 4,
        //一行的 Widget 数量
        // childAspectRatio: 0.7,
        //宽度和高度的比例
        children: goods.map((value) {
          return Container(
            decoration: BoxDecoration(
                border: Border.all(
                    color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)),
            child: Column(
              children: <Widget>[
                Image.network(
                  value['skillurl'],
                  width: 100,
                  height: 200,
                ),
                const SizedBox(height: 12),
                Text(
                  value['pordname'],
                  textAlign: TextAlign.center,
                  style: const TextStyle(fontSize: 20),
                )
              ],
            ),
          );
        }).toList(),
      ),
    );
  }
}

 最后展示的效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/315093.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索检索增强生成(RAG)技术的无限可能:Vector+KG RAG、Self-RAG、多向量检索器多模态RAG集成

探索检索增强生成&#xff08;RAG&#xff09;技术的无限可能&#xff1a;VectorKG RAG、Self-RAG、多向量检索器多模态RAG集成 由于 RAG 的整体思路是首先将文本切分成不同的组块&#xff0c;然后存储到向量数据库中。在实际使用时&#xff0c;将计算用户的问题和文本块的相似…

【C语言刷题每日一题#牛客网BC107】矩阵转置

目录 问题描述 思路逐步分析 完整代码实现 结果测试 问题描述 思路逐步分析 首先&#xff0c;根据输入的描述&#xff0c;第一行输入的是两个整数n和m&#xff0c;分别表示一个矩阵&#xff08;二维数组&#xff09;的行和列&#xff0c;并且行和列不超过10 根据要求&…

AC修炼计划(AtCoder Beginner Contest 335)A-F

传送门&#xff1a; AtCoder Beginner Contest 335 (Sponsored by Mynavi) - AtCoder A&#xff0c;B&#xff0c;C&#xff0c;D还算比较基础&#xff0c;没有什么思路&#xff0c;纯暴力就可以过。 这里来总结一下E和F E - Non-Decreasing Colorful Path 最开始以为是树形…

用笨办法-刻意练习来提高自己的编程能力

尝试了很多学习方法&#xff0c;企图快速提高编程能力&#xff0c;但最终发现&#xff0c;唯有老老实实刻意练习1&#xff0c;在辛苦与时间积累下&#xff0c;逐渐提升能力&#xff0c;才是最有效的方式。 将自己的笨办法总结了一下&#xff0c;主要包含7个步骤&#xff1a; …

Mariadb和mysql数据库的区别和相同之处

目 录 一、maridb 和mysql在linux系统中广泛应用 二、MySQL数据库 三、MariaDB数据库 四、MariaDB和MySQL有哪些相同点 五、MariaDB和MySQL的不同点 一、mariadb 和mysql在linux系统中广泛应用 用linux&#xff08;包括centos和Ubuntu&#xff09;的都知道&a…

构建基于RHEL7(CentOS7)的OpenSSH9.5p1的RPM包和升级回退方案

本文适用&#xff1a;RHEL7系列&#xff0c;或同类系统(CentOS7等) 文档形成时期&#xff1a;2023年 因软件世界之复杂和个人能力之限&#xff0c;难免疏漏和错误&#xff0c;欢迎指正。 文章目录 环境准备安装依赖openssh-9.5p1-el7.spec内容构建RPM包下载安装前注意事项开启t…

python学习笔记9(程序的描述方式、程序的组织结构、顺序结构、选择结构1)

&#xff08;一&#xff09;程序的描述方式 自然语言、流程图、伪代码 &#xff08;二&#xff09;程序的组织结构 顺序、选择、循环 &#xff08;三&#xff09;顺序结构 &#xff08;四&#xff09;选择结构1 if 1、条件写法1 2、如果只有一个判断的写法 3、注意冒号和缩进…

14、MySQL高频面试题

1、内连接和外连接的区别 内连接和外连接都是数据库进行多表联查时使用的连接方式&#xff0c;区别在于二者获取的数据集不同 内连接指的是使用左表中的每一条数据分别去连接右表中的每一条数据&#xff0c;仅仅显示出匹配成功的那部分 外连接有分为左外连接和右外连接 左外…

rke2 Online Deploy Rancher v2.8.0 latest (helm 在线部署 rancher v2.8.0)

文章目录 1. 简介2. 预备条件3. 安装 helm4. 安装 cert-manager4.1 yaml 安装4.2 helm 安装 5. 安装 rancher6. 验证7. 界面预览 1. 简介 Rancher 是一个 Kubernetes 管理工具&#xff0c;让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托…

RPA财务机器人在厦门市海沧医院财务管理流程优化汇总的应用

目前国内外研究人员对于RPA机器人在财务管理流程优化领域中的应用研究层出不穷&#xff0c;但现有研究成果主要集中在财务业务单一领域&#xff0c;缺乏财务管理整体流程一体化管控的研究。RPA机器人的功能绝非单一的财务业务处理&#xff0c;无论从自身技术发展&#xff0c;或…

【野火i.MX6NULL开发板】挂载 NFS 网络文件系统

0、前言 参考资料&#xff1a; &#xff08;误人子弟&#xff09;《野火 Linux 基础与应用开发实战指南基于 i.MX6ULL 系列》PDF 第22章 参考视频&#xff1a;&#xff08;成功&#xff09; https://www.bilibili.com/video/BV1JK4y1t7io?p26&vd_sourcefb8dcae0aee3f1aab…

Veeam Backup12安装备份恢复ESXI7.0 U3虚拟机

介绍 只需单个平台即可保护并管理所有工作负载、应用及数据&#xff1a;云端、虚拟、物理、SaaS、Kubernetes、VMware、Hyper-V、Windows、Linux、UNIX、NAS、AWS、Azure、企业应用等。 个人主要用于备份ESXi上的虚拟机&#xff0c;可以实现单次完整备份&#xff0c;和定时的…

SpringBoot请求参数加密、响应参数解密

SpringBoot请求参数加密、响应参数解密 1.说明 在项目开发工程中&#xff0c;有的项目可能对参数安全要求比较高&#xff0c;在整个http数据传输的过程中都需要对请求参数、响应参数进行加密&#xff0c;也就是说整个请求响应的过程都是加密处理的&#xff0c;不在浏览器上暴…

Windows下Redis5+可视化软件下载、安装和配置教程-2024年1月8日

Windows下Redis5下载、安装和配置教程-2024年1月8日 一、下载二、安装三、配置环境四、配置可视化客户端 一、下载 redis是现在是没有对win系统版进行维护的&#xff0c;这个是大神完成的&#xff0c;目前是到5版本&#xff0c;选择Redis-x64-5.0.14.1.zip点击下载 下载地址&…

Spring MVC 异常处理器

异常处理器 如果不加以异常处理&#xff0c;错误信息肯定会抛在浏览器页面上&#xff0c;这样很不友好&#xff0c;所以必须进行异常处理。 异常处理思路 系统的dao、service、controller出现都通过throws Exception向上抛出&#xff0c;最后由springmvc前端控制器交由异常处…

爬虫之使用代理

爬虫—使用代理 1. 为什么使用代理 1.1 让服务器以为不是同一个客户端在请求 1.2 防止我们的真实地址被泄漏&#xff0c;防止被追究 2. 理解使用代理的过程 3. 理解正向代理和反向代理的区别 通过上图可以看出&#xff1a; 正向代理&#xff1a;对于浏览器知道服务器的真实…

MySQL运维实战(3.1) MySQL官方客户端使用介绍

作者&#xff1a;俊达 引言 MySQL是MySQL安装包默认的客户端&#xff0c;该客户端程序通常位于二进制安装包的bin目录中&#xff0c;或者通过rpm安装包安装mysql-community-client&#xff0c;是数据库管理系统的重要组成部分。MySQL客户端不仅仅是一个简单的软件工具&#x…

RK3568驱动指南|第十一篇 pinctrl 子系统-第123章dt_node_to_map函数分析

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

【python入门】day26:统计字符串中出现指定字符的次数

案例 实际上if name“main”:就相当于是 Python 模拟的程序入口 。由于模块之间相互引用&#xff0c;不同模块可能都有这样的定义&#xff0c;而入口程序只能有一个&#xff0c;选中哪个入口程序取决于 ** ** name** **的值。 代码 #-*- coding:utf-8 -*- #开发时间&#xff…

第一波!2024年1月精选6款实用AI人工智能设计工具合集

大家好&#xff0c;这是进入2024年之后的第一波干货合集&#xff01;这次的干货合集还是以 AI 相关的设计干货开头&#xff0c;这次有了在本地无限制帮你清理图片中元素的 AI 工具&#xff0c;有知名免费图库出品的实时 AI 图片生成工具、将截图直接转化为代码的超强工具&#…