一文带你了解 Flutter dio封装

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
日志服务 SLS,月写入数据量 50GB 1个月
简介: 一文带你了解 Flutter dio封装

封装网络库考虑的几个方面:

  1. 请求参数的封装:将请求所需的参数进行封装,例如 URL、请求头、请求体等。可以定义一个统一的数据结构或模型类来表示请求参数,以便于传递和管理。
  2. 响应结果的封装:将网络请求返回的响应结果进行封装,例如状态码、响应头、响应体等。同样,可以定义一个统一的数据结构或模型类来表示响应结果,以便于处理和解析。
  3. 错误处理的封装:对网络请求可能出现的错误进行封装和处理,例如网络连接失败、超时、服务器错误等。可以定义自定义的异常类或错误码,以及相应的错误处理机制。
  4. 拦截器的封装:如果第三方网络库支持拦截器机制,你可以封装拦截器,用于在请求发起前或响应返回后进行额外的处理,如添加身份验证、日志记录等。

响应结果封装

  1. 响应状态码:获取响应的HTTP状态码,以判断请求是否成功或出现错误。常见的状态码有200表示成功,4xx表示客户端错误,5xx表示服务器错误等。
  2. 响应头(Headers):获取响应的头部信息,如Content-Type、Authorization等。根据接口要求和需要,提取并封装相应的响应头信息。
  3. 响应体(Body):获取响应的主体数据,通常是服务器返回的具体内容。根据接口要求和数据类型,将响应体进行适当的解析和处理,可以是JSON、文本、二进制数据等。
  4. 错误处理:根据响应状态码或其他错误标识,判断响应是否包含错误信息。如果存在错误,需要将错误信息进行封装和处理,以便在前端进行展示或进一步处理。
  5. 数据转换:根据接口返回的数据类型和需求,可能需要对响应数据进行适当的转换和格式化,以便在前端进行处理和展示。
  6. 异常处理:处理网络请求过程中可能出现的异常情况,如网络错误、超时等。提供友好的提示或错误处理机制,确保用户能够得到合适的反馈。

错误处理封装

  1. 错误码(Error Code):定义一套错误码,用于标识不同类型的错误。每个错误码应具有唯一性,并且可以根据错误码快速定位和处理错误。
  2. 错误信息(Error Message):为每个错误码提供相应的错误信息,以便在错误发生时能够提供清晰的错误描述。错误信息应该简明扼要、易于理解,并且能够帮助开发者或用户快速定位问题。
  3. 异常处理机制:针对可能出现的异常情况,如网络连接失败、请求超时等,需要实现相应的异常处理机制。这可以包括使用try-catch语句捕获异常、设置超时时间、重试机制等。
  4. 错误回调或异常抛出:根据具体情况,可以选择将错误通过回调函数返回给调用方,或者抛出异常供上层代码捕获和处理。这取决于项目的架构和开发者的偏好。
  5. 友好的错误提示:对于用户可见的错误,如接口调用失败或数据获取错误,需要提供友好的错误提示,以便用户能够理解并采取适当的操作。
  6. 日志记录:在错误处理中,建议记录相关的错误日志,包括错误码、错误信息、请求参数等,以便进行故障排查和问题定位。

默认配置项

我们在使用第三方网络库时,它会有相应的默认配置项的,配置好默认配置项时,为后面请求省了很多事。

那么常见的默认网络库配置项有如下:

  1. 请求方法(HTTP Method):通常默认为 GET 方法,用于获取资源。其他常见的请求方法包括 POST、PUT、DELETE 等。
  2. 请求超时时间(Timeout):默认情况下,网络库会设置一个请求超时时间,即在指定时间内没有收到服务器响应,则认为请求超时。默认超时时间通常为几秒钟,可以根据需要进行调整。
  3. 请求头(Headers):默认情况下,网络库不会添加任何请求头。你可以自定义请求头,例如添加身份验证信息、指定数据格式等。
  4. 响应数据格式(Response Format):网络库通常默认将响应数据解析为特定的格式,如 JSON、XML 或原始文本。你可以根据需要进行解析或更改默认格式。
  5. 连接池(Connection Pooling):一些网络库可能会使用连接池来管理与服务器的连接。连接池允许重复使用已建立的连接,以提高性能和效率。

本文会 讲Flutter dio 默认配置项:

dio BaseOptions 配置项源码:

BaseOptions({
  String? method, // 请求方法,默认为null,表示使用库的默认请求方法
  Duration? connectTimeout, // 连接超时时间,默认为null,表示使用库的默认超时时间
  Duration? receiveTimeout, // 接收超时时间,默认为null,表示使用库的默认超时时间
  Duration? sendTimeout, // 发送超时时间,默认为null,表示使用库的默认超时时间
  String baseUrl = '', // 基础URL,默认为空字符串
  Map<String, dynamic>? queryParameters, // 查询参数,默认为null
  Map<String, dynamic>? extra, // 额外配置参数,默认为null
  Map<String, dynamic>? headers, // 请求头,默认为null
  ResponseType? responseType = ResponseType.json, // 响应数据格式,默认为ResponseType.json,表示解析为JSON格式
  String? contentType, // 请求的Content-Type,默认为null
  bool Function(int?)? validateStatus, // 自定义验证响应状态码的函数,默认为null
  bool? receiveDataWhenStatusError, // 当响应状态码错误时是否继续接收数据,默认为null
  bool? followRedirects, // 是否跟随重定向,默认为null
  int? maxRedirects, // 最大重定向次数,默认为null
  bool? persistentConnection, // 是否保持持久连接,默认为null
  List<int> Function(String, RequestOptions)? requestEncoder, // 请求编码器,默认为null
  String? Function(List<int>, RequestOptions, ResponseBody)? responseDecoder, // 响应解码器,默认为null
  ListFormat? listFormat, // JSON数组的解析格式,默认为null
})

Demo

import 'package:dio/dio.dart';
class HttpApi { 
// 配置基本的请求选项
  static final BaseOptions options = BaseOptions(
    baseUrl: 'http://localhost:3001/', // 设置请求的基础 URL
    method: 'GET', //默认请求方法
    connectTimeout: const Duration(seconds: 5), // 设置连接超时时间为 5 秒
    receiveTimeout: const Duration(seconds: 3), // 设置接收超时时间为 3 秒
    headers: {
      'User-Agent': 'Dio', // 设置请求头信息
    },
  );
  static Dio dio = Dio(options);
}

拦截器

在Flutter中,Dio是一个强大的HTTP客户端库,它提供了拦截器(Interceptors)机制,用于在发送请求和接收响应之前进行额外的处理。拦截器可以用于添加身份验证、日志记录、错误处理等功能。

对于每个 dio 实例,我们可以添加一个或多个拦截器,通过这些拦截器,我们可以在处理请求、响应和错误之前拦截它们或 catchError。

内置拦截器

有的网路库它会内置一些拦截器,下面是 dio 内置的拦截器:

  1. LogInterceptor:用于打印请求和响应的日志信息。它可以帮助开发者调试和监控网络请求,包括请求方法、URL、请求头、请求体、响应状态码、响应头和响应体等。
  2. InterceptorsWrapper:这是一个包装类拦截器,它可以同时包含多个拦截器,并按照添加的顺序依次执行。通过使用InterceptorsWrapper,可以方便地组合多个拦截器,实现复杂的拦截器逻辑

List<Interceptor> inters = [];
inters.add(LogInterceptor()); //添加内置拦截器
dio.interceptors.addAll(inters);

自定义拦截器

自定义过滤器需要继承 DioInterceptor类并重写其方法来实现的。

在自定义拦截器中,我们可以在onRequest方法中处理请求前的逻辑,在onResponse方法中处理接收到响应后的逻辑onError方法中处理请求发生错误时的逻辑

// 自定义拦截器
class CustomInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // 在发送请求前的处理逻辑
    print('Request Interceptor - Request: ${options.uri}');
    print('我发送了请求啦--------');
    handler.next(options); // 继续执行下一个拦截器或发送请求
  }
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    // 在接收到响应后的处理逻辑
    print('Request Interceptor - Response: ${response.statusCode}');
    print('我收到请求啦--------');
    handler.next(response); // 继续执行下一个拦截器或返回响应
  }
  @override
  // ignore: deprecated_member_use
  void onError(DioError err, ErrorInterceptorHandler handler) {
    // 在请求发生错误时的处理逻辑
    print('Request Interceptor - Error: ${err.message}');
    handler.next(err); // 继续执行下一个拦截器或抛出错误
  }
}

发起请求

上面我已经把网络库的 默认配置项,拦截器都配置好了,接下来就是开始发起请求了。我可以把发起请求做个简单封装,把可变的参数提供去,这样每次再发起请求时,只需要传递参数就可以了。

try {
      Response response =
          await dio.request<T>(url, queryParameters: params, options: options);
      return response.data;
    } catch (e) {
      print(e);
      return Future.error(e);
}

完整封装代码

/*
 * @Author: HaiJun
 * @Date: 2023-08-15 14:13:54
 * @LastEditTime: 2023-08-16 14:29:43
 * @FilePath: \flutter_demo_show\lib\utils\http.dart
 * @Description: 
 * 
 */
import 'package:dio/dio.dart';
import './CustomInterceptor.dart';
class HttpApi {
  // 配置基本的请求选项
  static final BaseOptions options = BaseOptions(
    baseUrl: 'http://localhost:3001/', // 设置请求的基础 URL
    method: 'GET', //默认请求方法
    connectTimeout: const Duration(seconds: 5), // 设置连接超时时间为 5 秒
    receiveTimeout: const Duration(seconds: 3), // 设置接收超时时间为 3 秒
    headers: {
      'User-Agent': 'Dio', // 设置请求头信息
    },
  );
  static Dio dio = Dio(options);
  static Future<T> request<T>(String url,
      {String method = "get", Map<String, dynamic>? params}) async {
    // 1请求的单独配置
    final options = Options(method: method);
    // 2 添加一个拦截器
    Interceptor inter = InterceptorsWrapper(
      onRequest: (options, handler) {
        return handler.next(options);
      },
      onResponse: (e, handler) {
        print(e);
        return handler.next(e);
      },
      onError: (e, handler) {
        print(e);
        return handler.next(e);
      },
    );
    List<Interceptor> inters = [];
    inters.add(CustomInterceptor()); //添加自定义拦截器
    inters.add(LogInterceptor()); //添加内置拦截器
    dio.interceptors.addAll(inters);
    // 3 发起网络请求
    try {
      Response response =
          await dio.request<T>(url, queryParameters: params, options: options);
      print("测试");
      print(url);
      return response.data;
    } catch (e) {
      print(e);
      return Future.error(e);
    }
  }
}

调用请求

把封装好的文件导入进来,

import 'package:flutter/material.dart';
import 'utils/http.dart';
class MyNetwork extends StatefulWidget {
  const MyNetwork({super.key});
  @override
  State<MyNetwork> createState() => _MyNetworkState();
}
class _MyNetworkState extends State<MyNetwork> {
  void getData() async {
    print("发起请求");
    var responseData = await HttpApi.request('book');
    print(responseData);
  }
  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(children: [
      ElevatedButton(
          onPressed: () {
            getData();
          },
          child: const Text("发起请求"))
    ]));
  }
}

utils/http.dart文件中,我们封装了 dio ,创建了dio示例,传入了默认配置项,并且绑定了拦截器,在发起请求时,也会走请求拦截器,看参数是否合法,后会进入响应拦截器,状态码是否对以及不同状态码返回不同内容,最后将返回结果数据抛给客户端响应。

utils/http.dart文件中, 有一个 request异步 静态(static)方法,它提供了请求时需要填的必填参数和可选参数,当我们使用时,可以通过 类名.方法名 即可调用发起请求了。

请求返回内容

相关文章
|
3月前
|
存储 缓存 JavaScript
Flutter 学习之封装 WebView
【10月更文挑战第24天】通过以上的探讨,我们可以看出,在 Flutter 中封装 WebView 是非常有必要的,它可以提高代码的复用性、增强可维护性、提供统一接口。在实际应用中,我们需要根据具体的需求和场景,选择合适的封装方法和技术,以实现更好的效果。
|
3月前
|
存储 缓存 Dart
Flutter&鸿蒙next 封装 Dio 网络请求详解:登录身份验证与免登录缓存
本文详细介绍了如何在 Flutter 中使用 Dio 封装网络请求,实现用户登录身份验证及免登录缓存功能。首先在 `pubspec.yaml` 中添加 Dio 和 `shared_preferences` 依赖,然后创建 `NetworkService` 类封装 Dio 的功能,包括请求拦截、响应拦截、Token 存储和登录请求。最后,通过一个登录界面示例展示了如何在实际应用中使用 `NetworkService` 进行身份验证。希望本文能帮助你在 Flutter 中更好地处理网络请求和用户认证。
221 1
|
3月前
|
Dart UED 开发者
Flutter&鸿蒙next中的按钮封装:自定义样式与交互
在Flutter应用开发中,按钮是用户界面的重要组成部分。Flutter提供了多种内置按钮组件,但有时这些样式无法满足特定设计需求。因此,封装一个自定义按钮组件变得尤为重要。自定义按钮组件可以确保应用中所有按钮的一致性、可维护性和可扩展性,同时提供更高的灵活性,支持自定义颜色、形状和点击事件。本文介绍了如何创建一个名为CustomButton的自定义按钮组件,并详细说明了其样式、形状、颜色和点击事件的处理方法。
111 1
|
3月前
|
开发工具 UED
Flutter&鸿蒙next中封装一个输入框组件
本文介绍了如何创建一个简单的Flutter播客应用。首先,通过`flutter create`命令创建项目;接着,在`lib`目录下封装一个自定义输入框组件`CustomInput`;然后,在主应用文件`main.dart`中使用该输入框组件,实现简单的UI布局和功能;最后,通过`flutter run`启动应用。本文还提供了后续扩展建议,如状态管理、网络请求和UI优化。
119 1
|
3月前
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
67 0
|
3月前
|
Dart 安全 UED
Flutter&鸿蒙next中的表单封装:提升开发效率与用户体验
在移动应用开发中,表单是用户与应用交互的重要界面。本文介绍了如何在Flutter中封装表单,以提升开发效率和用户体验。通过代码复用、集中管理和一致性的优势,封装表单组件可以简化开发流程。文章详细讲解了Flutter表单的基础、封装方法和表单验证技巧,帮助开发者构建健壮且用户友好的应用。
104 0
|
7月前
|
JSON Dart API
Flutter dio http 封装指南说明
本文介绍了如何实现一个通用、可重构的 Dio 基础类,包括单例访问、日志记录、常见操作封装以及请求、输出、报错拦截等功能。
178 2
Flutter dio http 封装指南说明
|
6月前
|
存储 缓存 安全
Flutter Dio进阶:使用Flutter Dio拦截器实现高效的API请求管理和身份验证刷新
Flutter Dio进阶:使用Flutter Dio拦截器实现高效的API请求管理和身份验证刷新
690 0
|
27天前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
70 18
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
20天前
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
18 1

热门文章

最新文章

  • 1
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 2
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 3
    【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
  • 4
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 5
    flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈
  • 6
    【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
  • 7
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 8
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 9
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 10
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
  • 1
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
    39
  • 2
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
    25
  • 3
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    130
  • 4
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    27
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    68
  • 6
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    85
  • 7
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    67
  • 8
    flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
    18
  • 9
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    23
  • 10
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    114