Flutter网络请求封装:高效、灵活、易用的Dio工具类

embedded/2025/3/30 8:58:44/

在Flutter开发中,网络请求是必不可少的功能。为了简化代码、提高开发效率,我们通常会封装一个网络请求工具类。本文基于Dio库,详细介绍如何封装一个高效、灵活、易用的网络请求工具类,支持以下功能:

  1. 单例模式:确保全局只有一个Dio实例,避免资源浪费。
  2. 动态配置:支持运行时动态修改baseUrlheaders等配置。
  3. 拦截器:内置日志拦截器,并支持添加自定义拦截器。
  4. 错误处理:提供详细的错误信息,支持自定义错误处理逻辑。
  5. 文件上传和下载:封装了文件上传和下载功能。
  6. 取消请求:支持取消正在进行的请求。
  7. 模块化设计:代码结构清晰,便于维护和扩展。

通过本文,你将学会如何封装一个功能强大的网络请求工具类,并直接应用到你的Flutter项目中。


代码实现

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';class HttpUtil {// 单例模式static final HttpUtil _instance = HttpUtil._internal();factory HttpUtil() => _instance;HttpUtil._internal() {_init();}late Dio _dio;final List<Interceptor> _interceptors = []; // 自定义拦截器列表CancelToken _cancelToken = CancelToken(); // 用于取消请求// 初始化void _init() {_dio = Dio(BaseOptions(baseUrl: 'https://your-api-url.com', // 默认基础地址connectTimeout: const Duration(seconds: 5), // 连接超时时间receiveTimeout: const Duration(seconds: 5), // 接收数据超时时间headers: {'Content-Type': 'application/json; charset=UTF-8',},));// 添加默认拦截器_dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {if (kDebugMode) {print('Request: ${options.method} ${options.path}');}return handler.next(options);},onResponse: (response, handler) {if (kDebugMode) {print('Response: ${response.statusCode} ${response.data}');}return handler.next(response);},onError: (DioException e, handler) {if (kDebugMode) {print('Error: ${e.message}');}return handler.next(e);},));// 添加自定义拦截器for (var interceptor in _interceptors) {_dio.interceptors.add(interceptor);}}// 添加自定义拦截器void addInterceptor(Interceptor interceptor) {_interceptors.add(interceptor);_dio.interceptors.add(interceptor);}// 动态更新基础配置void updateBaseConfig({String? baseUrl,Duration? connectTimeout,Duration? receiveTimeout,Map<String, dynamic>? headers,}) {_dio.options.baseUrl = baseUrl ?? _dio.options.baseUrl;_dio.options.connectTimeout = connectTimeout ?? _dio.options.connectTimeout;_dio.options.receiveTimeout = receiveTimeout ?? _dio.options.receiveTimeout;_dio.options.headers = headers ?? _dio.options.headers;}// GET请求Future<Response> get(String path, {Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {return _request(path,method: 'GET',queryParameters: queryParameters,options: options,cancelToken: cancelToken,);}// POST请求Future<Response> post(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {return _request(path,method: 'POST',data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,);}// PUT请求Future<Response> put(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {return _request(path,method: 'PUT',data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,);}// DELETE请求Future<Response> delete(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {return _request(path,method: 'DELETE',data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,);}// 文件上传Future<Response> upload(String path, {required String filePath,Map<String, dynamic>? data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {final formData = FormData.fromMap({...data ?? {},'file': await MultipartFile.fromFile(filePath),});return _request(path,method: 'POST',data: formData,queryParameters: queryParameters,options: options,cancelToken: cancelToken,);}// 文件下载Future<Response> download(String urlPath,String savePath, {Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {try {final response = await _dio.download(urlPath,savePath,queryParameters: queryParameters,options: options,cancelToken: cancelToken ?? _cancelToken,);return response;} on DioException catch (e) {throw _handleError(e);}}// 通用请求方法Future<Response> _request(String path, {required String method,dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,}) async {try {final response = await _dio.request(path,data: data,queryParameters: queryParameters,options: Options(method: method),cancelToken: cancelToken ?? _cancelToken,);return response;} on DioException catch (e) {throw _handleError(e);}}// 取消请求void cancelRequests({CancelToken? cancelToken}) {if (cancelToken == null) {_cancelToken.cancel('Request cancelled');_cancelToken = CancelToken(); // 重置CancelToken} else {cancelToken.cancel('Request cancelled');}}// 错误处理String _handleError(DioException e) {switch (e.type) {case DioExceptionType.connectionTimeout:return '连接超时';case DioExceptionType.sendTimeout:return '发送请求超时';case DioExceptionType.receiveTimeout:return '接收数据超时';case DioExceptionType.badResponse:return '服务器返回错误: ${e.response?.statusCode}';case DioExceptionType.cancel:return '请求已取消';case DioExceptionType.unknown:return '未知错误: ${e.message}';default:return '网络错误: ${e.message}';}}
}

使用示例

void fetchData() async {try {final response = await HttpUtil().get('/api/data');print('Data: ${response.data}');} catch (e) {print('Error: $e');}
}void uploadFile() async {try {final response = await HttpUtil().upload('/api/upload',filePath: '/path/to/file',);print('Upload Response: ${response.data}');} catch (e) {print('Error: $e');}
}void cancelRequest() {HttpUtil().cancelRequests();
}

总结

通过封装这样一个网络请求工具类,我们可以显著提高Flutter项目的开发效率,减少重复代码,同时增强代码的可维护性和扩展性。希望本文对你有所帮助


http://www.ppmy.cn/embedded/177088.html

相关文章

优选算法的睿智之林:前缀和专题(二)

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 一、例题讲解 1.1. 和为 K 的子数组 我们先来思考暴力枚举&#xff1a;利用双指针left和right&#xff0c;当right移动到某一个位置时&#xff0c;left与right构成的区间之和为k时&#xff0c;此时right不能停止…

Qt 线程类

线程类 这些类与线程应用程序相关。 Concurrent Filter and Filter-Reduce 并行地从序列中选择值并组合它们 Concurrent Map and Map-Reduce 并行地从序列中转换值并组合它们 Concurrent Run 在单独线程中运行任务的简单方法 Concurrent Task 在独立线程中运行任务的可…

MCP(大模型上下文协议)

以下是关于大模型MCP协议&#xff08;Model Context Protocol&#xff09;的详细介绍&#xff0c;综合其定义、技术架构、应用场景及行业影响&#xff1a; 一、定义与核心目标 **MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;**是由Anthropic…

html5炫酷3D立体文字效果实现详解

炫酷3D立体文字效果实现详解 这里写目录标题 炫酷3D立体文字效果实现详解项目概述技术实现要点1. 基础布局设置2. 动态背景效果3. 文字渐变效果4. 立体阴影效果5. 悬浮动画效果 技术难点及解决方案1. 文字渐变动画2. 立体阴影效果3. 性能优化 浏览器兼容性总结 项目概述 在这个…

SpringCould微服务架构之Docker(4)

Docker ce是社区版。 安装docker之前&#xff0c;先安装yum-util 。 安装docker之前&#xff0c;一定要先关闭防火墙。

多源最短路:Floyd算法の暴力美学

多源最短路求解的是图中的任意两个节点之间的最短路。 前文我们已经讲过单源最短路&#xff0c;我们完全可以做n次单源最短路算法&#xff0c;求出任意两节点的最短距离。最快的堆优化版的 dijkstra 算法的时间复杂度为o&#xff08;m * logm&#xff09;&#xff0c;枚举n次时…

(Arxiv-2025)MagicDistillation:用于大规模人像少步合成的弱到强视频蒸馏

MagicDistillation&#xff1a;用于大规模人像少步合成的弱到强视频蒸馏 paper是HKUST发布在Arxiv 2025的工作 paper title&#xff1a;MagicDistillation: Weak-to-Strong Video Distillation for Large-Scale Portrait Few-Step Synthesis Project page&#xff1a;地址 Abst…

SVN常用命令

SVN常用命令 基本操作命令 • 检出代码&#xff08;Checkout&#xff09;&#xff1a;从SVN服务器获取代码到本地。 svn checkout [svn服务器url] [检出本地的path] 示例&#xff1a; svn checkout svn://47.106.183.193/helloworld ./ • 提交代码&#xff08;Commit&…