Flutter dio 使用 注意事项
dio 配置抓包代理
需要通过以下代码才能设置代理。
//是否开启抓包功能static const bool isProxyEnable = true;//设置代理服务器地址和端口static const String proxy = "192.168.7.134:8888";init(){...
//配置可以通过Fiddler抓包if(isProxyEnable){(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =(client) {client.badCertificateCallback =(X509Certificate cert, String host, int port) {return isProxyEnable &&DebugModelUtil.isDebugMode;};client.findProxy = (url) {return 'PROXY $proxy' ;};};} }
以上方法使用了一个工具用来判断app在debug模式还是release模式下
import 'package:flutter/foundation.dart';bool _debug = kDebugMode; //constant下的一个常量bool _release = kReleaseMode; //constant下的一个常量///用于判断是否在debug模式下
class DebugModelUtil {static bool get isDebugMode {return _debug;}
}
post请求 参数需要放在data中
错误情况
测试代码如下,如果放在queryParameters 中,将会拼接到url中。
Map<String, dynamic> params = {};params['name']='zhangshan&a b c';params['age']=24;params['language']='中文';HttpUtil.dio.post('http://192.168.1.1',queryParameters: params,);
fiddler抓包如下
正确情况
测试代码
Map<String, dynamic> params = {};params['name'] = 'zhangshan&a b c';params['age'] = 24;params['language'] = '中文';HttpUtil.dio.post('http://192.168.1.1',data: params,);
fiddler抓包结果
指定content-type
在默认情况下,dio的content-type使用的是 application/json; charset=utf-8 而要使用其他的content-type。需要如下使用,有两种方法
通过header指定
代码如下
Map<String, dynamic> params = {};params['name'] = 'zhangshan&a b c';params['age'] = 24;params['language'] = '中文';HttpUtil.dio.post('http://192.168.1.1',data: params,options: Options(headers: {Headers.contentTypeHeader:Headers.formUrlEncodedContentType}));
抓包结果如下:
通过content-type指定
代码如下
Map<String, dynamic> params = {};params['name'] = 'zhangshan&a b c';params['age'] = 24;params['language'] = '中文';HttpUtil.dio.post('http://192.168.1.1',data: params,options: Options(contentType: 'application/x-www-form-urlencoded'));
抓包结果
以上两种方法需要注意的点如下
内容不一样,header中使用的是一个Headers中的常量内容是application/x-www-form-urlencoded;charset=utf-8 而contentType中并没有charset这部分。
如果指定了类型为application/x-www-form-urlencoded 则dio会对data中的数据自动编码。比如中文和空格。在抓包结果中可以看到。
multipart/form-data 不支持这种方式,下面会介绍。
使用 multipart/form-data (附带上传文件)
上面介绍的方法对multipart/form-data 这种类型不支持。需要单独编码。因为这种类型比较复杂,还可以上传文件。
测试代码
Map params = {};params['name']='zhangshan&a b c';params['age']=24;params['language']='中文';//上传文件var mtp= MultipartFile.fromString('abcdef',filename: 'text.file') ;//携带其他参数var formData = FormData.fromMap({'file':mtp,...params});HttpUtil.dio.post('http://newapp.jyb.cn/app_pub/',data: formData,);
抓包结果
MultipartFile类具有很多方便的静态方法,可以很轻松的获取一个文件。
指定返回类型
如果你请求的时候指定了返回类型,dio会自动帮你转化,比如你指定类型为一个json。则拿到的response.data 属性就会是一个Map。 这个主要是通过设置option的responseType来实现的。
代码如下
Map params = {};params['name']='zhangshan&a b c';params['age']=24;params['language']='中文';HttpUtil.dio.post('http://newapp.jyb.cn/app_pub/',data: params,options: Options(responseType: ResponseType.json));
附带一个网络访问工具的封装
import 'dart:io';import 'package:connectivity/connectivity.dart';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio_http_cache/dio_http_cache.dart';
import 'package:dio_log/interceptor/dio_log_interceptor.dart';
import 'package:tibet_wxb/common/http/mock_data_interceptor.dart';
import 'package:tibet_wxb/common/util/dev_model_check.dart';
import 'package:tibet_wxb/common/util/web_util.dart';typedef JsonParseFun<T> = T Function(Map<String, dynamic> json);
typedef StringParseFun<T> = T Function(String str);enum DioMethod {get,post,put,delete,patch,head,
}class HttpUtil {static late Dio _dio;static const int _connectTimeout = 30 * 1000; //15sstatic const int _receiveTimeout = 30 * 1000;static const int _sendTimeout = 30 * 1000;static DioCacheManager? _dioCacheManager;//是否开启抓包功能static const bool isProxyEnable = true;//设置代理服务器地址和端口static const String proxy = "192.168.7.134:8888";static init() {/// 全局属性:请求前缀、连接超时时间、响应超时时间var options = BaseOptions(/// 请求的Content-Type,默认值是"application/json; charset=utf-8"./// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,/// 可以设置此选项为 `Headers.formUrlEncodedContentType`, 这样[Dio]就会自动编码请求体.responseType: ResponseType.json,validateStatus: (status) {// 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)return true;},connectTimeout: _connectTimeout,receiveTimeout: _receiveTimeout,sendTimeout: _sendTimeout,);_dio = Dio(options);//添加网络日志监听_dio.interceptors.add(DioLogInterceptor());//添加网络缓存if (PlatformUtil.isInMobile) {_dioCacheManager = DioCacheManager(CacheConfig());_dio.interceptors.add(_dioCacheManager!.interceptor);}//添加对模拟数据的处理_dio.interceptors.add(MockDataInterceptor());//配置可以通过Fiddler抓包if(isProxyEnable){(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =(client) {client.badCertificateCallback =(X509Certificate cert, String host, int port) {return isProxyEnable &&DebugModelUtil.isDebugMode;};client.findProxy = (url) {return 'PROXY $proxy' ;};};}}static void clearCache() {_dioCacheManager!.clearAll();}static Dio get dio{return _dio;}//只获取stringstatic Future<String> requestString<T>(String path, {DioMethod method = DioMethod.get,Map<String, dynamic>? params,Map<String, dynamic>? headers,data,CancelToken? cancelToken,Options? options,ProgressCallback? onSendProgress,ProgressCallback? onReceiveProgress,}) async {options??=Options();var str = await request<String>(path,stringParseFun: (str)=>str,method: method,params: params,headers: headers,data: data,cancelToken: cancelToken,options: options.copyWith(responseType: ResponseType.plain),onSendProgress: onSendProgress,onReceiveProgress: onReceiveProgress,);return str ?? "";}/// 对网络访问的统一封装/// 如果请求的数据是string的话,那么需要传入stringParseFun 方法/// 如果返回的数据格式是json的话,需要传入jsonParseFun 方法static Future<T?> request<T>(String path, {JsonParseFun<T>? jsonParseFun,StringParseFun<T>? stringParseFun,DioMethod method = DioMethod.get,Map<String, dynamic>? params,Map<String, dynamic>? headers,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();options=options.copyWith(method: _methodValues[method],headers: headers);print('options content type is ${options.contentType}');try {Response response;response = await _dio.request(path,data: data,queryParameters: params,cancelToken: cancelToken,options: options,onSendProgress: onSendProgress,onReceiveProgress: onReceiveProgress);if (response.statusCode == 200) {if (stringParseFun != null) {return stringParseFun(response.data);}if (response.data is Map && jsonParseFun != null) {return jsonParseFun(response.data);}} else {throw DioError(requestOptions: response.requestOptions,type: DioErrorType.other,response: response,error: "服务器错误:状态码为" + response.statusCode.toString());}} on DioError catch (e) {onErrorInterceptor(e);rethrow;}}// 对错误添加更好的语义化处理static void onErrorInterceptor(DioError err) async {// 异常分类switch (err.type) {// 4xx 5xx responsecase DioErrorType.response:err.requestOptions.extra["errorMsg"] = err.response?.data ?? "连接异常";break;case DioErrorType.connectTimeout:err.requestOptions.extra["errorMsg"] = "连接超时";break;case DioErrorType.sendTimeout:err.requestOptions.extra["errorMsg"] = "发送超时";break;case DioErrorType.receiveTimeout:err.requestOptions.extra["errorMsg"] = "接收超时";break;case DioErrorType.cancel:err.requestOptions.extra["errorMsg"] =err.message.isNotEmpty ? err.message : "取消连接";break;case DioErrorType.other:default:var connectivityResult = await (Connectivity().checkConnectivity());//判断是否有网络if (connectivityResult == ConnectivityResult.none) {err.requestOptions.extra["errorMsg"] = "网络未连接";break;}err.requestOptions.extra["errorMsg"] = "连接异常";break;}}
}
对模拟数据的支持
使用拦截器实现
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'dart:convert';class MockDataInterceptor extends Interceptor{static const String local_path='http://127.0.0.1/';@overrideFuture<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {var path = options.path;if(path.startsWith(local_path)){try{String relPath= "assets/mock_data/"+path.substring(local_path.length);String jsonStr=await rootBundle.loadString(relPath);Response response=Response(requestOptions: options);response.data=json.decode(jsonStr);response.statusCode=200;handler.resolve(response);}catch (e){DioError dioError=DioError(requestOptions: options,error: "解析模拟数据错误$e");handler.reject(dioError);}}else{handler.next(options);}}
}
Flutter dio 使用 注意事项相关推荐
- Flutter Dio的简易封装和demo
flutter_net_demo 一个简单的flutter dio的封装, 包括: 日志打印, 网络进度, 返回json转bean, get post upload方法的封装, 简易可直接运行的dem ...
- Flutter Dio 网络接口与请求数据
Flutter Dio 网络接口与请求数据 想了想,感觉没什么好说的,像什么get,post,delete,download啥的,基本插件的使用文档都有,没什么好说的,但是我们实际项目写的时候,可不能 ...
- Flutter - dio 简单二次封装
demo 地址: https://github.com/iotjin/jh_flutter_demo Flutter Dio简单二次封装和自定义Header Flutter Dio二次封装 Flutt ...
- Flutter —— dio
Flutter -- dio 1. 关于import 2. pubspec 3. Dio 4. 替换项目三方库 1. 关于import import 中 as关键字来给他起了个别名来避免类名.方法名冲 ...
- Flutter dio XMLHttpRequest error
Flutter dio XMLHttpRequest error 原文:https://blog.csdn.net/weixin_44259356/article/details/105601933 ...
- flutter dio+rxdart
线上flutter 接口请求基本架构(线上实际项目搭建 不多讲直接上代码) 首先添加库: pubspec.yaml 目录下: dio: ^2.1.2 #dio 请求框架rxdart: ^0.21.0 ...
- flutter dio 示例
GIT HUB常常打不开,保存一份以方便随时查看. 示例 发起一个 GET 请求 : Response response; var dio = Dio(); response = await dio. ...
- Flutter dio 文件上传下载
Dio 是Flutter 网络请求的Pub包 Dio除了常用的get post 还可以文件下载 上传等操作 关于文件分片上传 或者文件下载 用到的pub 包 #文件选择file_selector: ^ ...
- Flutter Dio包网络请求抓包解决方案
在Flutter中进行网络请求时,我们可以使用的库有3个,即Http请求库.HttpClient请求库和Dio请求库(详细介绍请参考:Flutter开发之Http网络请求),使用得最多的就是Dio请求 ...
最新文章
- 微软发布代码智能新基准数据集CodeXGLUE,多角度衡量模型优劣
- MyEclipse极速优化
- 计算机科学与技术python方向是什么意思-计算机科学与技术专业大学应该掌握什么样的基本技能?...
- LRUCache 具体解释
- NoSQL数据库探讨之一 - 为什么要用非关系数据库?
- linux find命令详解--转
- 数字统计1(数组下标法)
- 【H.264/AVC视频编解码技术】第二章【H264码流分析】
- pta输出三角形字符阵列c语言,C语言l|博客园作业11
- java四则出题判分_java 随机出题四则运算
- 扎克伯格拒绝参加加拿大议会 或因藐视罪名被拘留
- 哪里有高中教师教学计算机能力培训,04060406_王世红_高中教师信息技术能力的培训.doc...
- 《原力计划【第二季】》第 7 周周榜揭晓!!!
- C++ 以智能指针管理内存资源
- ui-router 之 $state.go
- CWE-120: Buffer Copy without Checking Size of Input(不检查输入数据大小就复制缓冲区)
- 【科研工具】【MikTex】MikTex安装和使用
- 用二叉树表示家谱关系并实现各种查找功能
- 华为云迁移工具推荐最佳实践:Xen虚拟化迁移到华为云
- html 设置响应X-frame,X-Frame-Options(点击劫持)漏洞分析及web配置修复