前言

由于刚过完年工作比较紧张,文章已经四周没有更新了,非常抱歉!接下来依然会尽量保持每周更新!

本篇介绍Flutter中网络请求相关api的使用,Flutter在Flutter engine中提供了一个sky_engine开发工具包,其包含了一个_http的库,该库中有封装的http请求相关的各种操作类。本文我们将介绍_http相关操作类的使用和基于_http封装的三方dio网络库的使用。

自带网络库_http

_http库中的http.dart文件中封装的HttpClient类是我们常用的网络请求操作类,该类是一个抽象类,其具体操作由http_impl.dart文件中_HttpClient类实现,该类中封装了各种http请求的方法,包括getpostputdeletepatchhead等请求。

getpost请求方法是我们常用的两种方法,通过下面的例子看下其使用方法。

_getHttpData() async {    var httpClient = new HttpClient();    //为charles抓包设置代理,为什么在代码中设置?请参考上篇文章。    httpClient.findProxy = (url) {      return HttpClient.findProxyFromEnvironment(url, environment: {"http_proxy": 'http://192.168.124.94:8888',});    };    //请求参数设置    Map queryParameters = {'format': '2', 'key': '939e592487c33b12c509f757500888b5', 'lon': '116.39277', 'lat': '39.933748'};    var uri = Uri.http('v.juhe.cn', '/weather/geo', queryParameters);    var request = await httpClient.getUrl(uri);    //下面一行是post请求    //var request = await httpClient.postUrl(uri);    var response = await request.close();    if (response.statusCode == 200) {      print('请求成功');      var responseBody = await response.transform(utf8.decoder).join();      print('responseBody = $responseBody');    } else {      print('请求失败');    }}

以上代码中httpClient.getUrl(uri)方法即是根据uri发起get请求,post请求用法和get请求只是调用方法不同,包括参数设置等其他用法都一样。请求抓包结果如下:

  • get请求

  • post请求

请求成功之后以上代码输出结果如下:

I/flutter (19183): 请求成功I/flutter (19183): responseBody={"resultcode":"200","reason":"查询成功","result":{"sk":{"temp":"8","wind_direction":"西南风","wind_strength":"2级","humidity":"51%","time":"21:54"},"today":{"temperature":"1℃~15℃","weather":"晴","weather_id":{"fa":"00","fb":"00"},"wind":"南风微风","week":"星期五","city":"北京","date_y":"2019年03月01日","dressing_index":"较冷","dressing_advice":"建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。","uv_index":"中等","comfort_index":"","wash_index":"较适宜","travel_index":"较不宜","exercise_index":"较不宜","drying_index":""},"future":[{"temperature":"1℃~15℃","weather":"晴","weather_id":{"fa":"00","fb":"00"},"wind":"南风微风","week":"星期五","date":"20190301"},{"temperature":"3℃~15℃","weather":"霾","weather_id":{"fa":"53","fb":"53"},"wind":"西南风微风","week":"星期六","date":"20190302"},{"temperature":"3℃~15℃","weather":"霾转晴","weather_id":{"fa":"53","fb":"00"},"wind":"西南风微风","

由此可以看出结果输出不完整,部分字符串被丢弃了,前段时间有个同学留言问过这个问题,在这里说明一下。Flutter官方文档有这个问题的说明:

The Dart print() function outputs to the system console, which you can view using flutter logs (which is basically a wrapper around adb logcat).

If you output too much at once, then Android sometimes discards some log lines. To avoid this, you can use debugPrint(), from Flutter’s foundation library. This is a wrapper around print which throttles the output to a level that avoids being dropped by Android’s kernel.

具体地址在:

https://flutter.dev/docs/testing/debugging#print-and-debugprint-with-flutter-logs

官方建议我们输出日志过多的时候使用debugPrint()函数,作者使用debugPrint()函数之后发现依然是输出不完整,查看debugPrint()函数的具体代码实现后发现以上输出的内容是一行的内容,一行内容过多的情况下debugPrint()函数依然无法完整进行输出,最后我采用了一个技巧,对以上返回的responseBody结果进行了简单处理,根据特殊字符串进行字符串替换,加入换行符,代码如下:

var responseBody = await response.transform(utf8.decoder).join();//‘{’符号前加个换行符responseBody = responseBody.replaceAll("{", "\n{");debugPrint('responseBody=$responseBody');

于是输出了完整的请求返回结果:

I/flutter (19183): 请求成功I/flutter (19183): responseBody=I/flutter (19183): {"resultcode":"200","reason":"successed!","result":I/flutter (19183): {"sk":I/flutter (19183): {"temp":"8","wind_direction":"西南风","wind_strength":"2级","humidity":"51%","time":"22:09"},"today":I/flutter (19183): {"temperature":"1℃~15℃","weather":"晴","weather_id":I/flutter (19183): {"fa":"00","fb":"00"},"wind":"南风微风","week":"星期五","city":"北京","date_y":"2019年03月01日","dressing_index":"较冷","dressing_advice":"建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。","uv_index":"中等","comfort_index":"","wash_index":"较适宜","travel_index":"较不宜","exercise_index":"较不宜","drying_index":""},"future":[I/flutter (19183): {"temperature":"1℃~15℃","weather":"晴","weather_id":I/flutter (19183): {"fa":"00","fb":"00"},"wind":"南风微风","week":"星期五","date":"20190301"},I/flutter (19183): {"temperature":"3℃~15℃","weather":"霾","weather_id":I/flutter (19183): {"fa":"53","fb":"53"},"wind":"西南风微风","week":"星期六","date":"20190302"},I/flutter (19183): {"temperature":"3℃~15℃","weather":"霾转晴","weather_id":I/flutter (19183): {"fa":"53","fb":"00"},"wind":"西南风微风","week":"星期日","date":"20190303"},I/flutter (19183): {"temperature":"2℃~15℃","weather":"晴","weather_id":I/flutter (19183): {"fa":"00","fb":"00"},"wind":"北风微风","week":"星期一","date":"20190304"},I/flutter (19183): {"temperature":"3℃~16℃","weather":"晴","weather_id":I/flutter (19183): {"fa":"00","fb":"00"},"wind":"北风微风","week":"星期二","date":"20190305"},I/flutter (19183): {"temperature":"3℃~15℃","weather":"霾","weather_id":I/flutter (19183): {"fa":"53","fb":"53"},"wind":"西南风微风","week":"星期三","date":"20190306"},I/flutter (19183): {"temperature":"3℃~15℃","weather":"霾","weather_id":I/flutter (19183): {"fa":"53","fb":"53"},"wind":"西南风微风","week":"星期四","date":"20190307"}]},"error_code":0}

第三方网络库dio

dio是目前使用最多的Flutter三方网络库,它是对http请求的一个封装,功能非常强大,支持拦截器、全局配置、表单数据、请求取消、文件下载、超时等。目前dio的最新版本为2.0.15,2.x版本对1.x版本代码进行了一些重构,所以之前使用过1.x版本的同学,再升级到2.x时要注意需要修改一些代码。

下面基于2.0.15版本举个请求天气信息的例子:

  Future _getWeatherInfo() async {    Dio dio = Dio();    //设置代理    DefaultHttpClientAdapter adapter = dio.httpClientAdapter;    adapter.onHttpClientCreate = (HttpClient client) {      if(client == null) {        client = HttpClient();      }      client.findProxy = (url) {        return HttpClient.findProxyFromEnvironment(url, environment: {"http_proxy": 'http://192.168.124.94:8888',});      };      return client;    };    dio.options.baseUrl = "http://v.juhe.cn/";    //设置连接超时时间    dio.options.connectTimeout = 10000;    //设置数据接收超时时间    dio.options.receiveTimeout = 10000;    try {        //以表单的形式设置请求参数      Map queryParameters = {'format': '2', 'key': '939e592487c33b12c509f757500888b5', 'lon': '116.39277', 'lat': '39.933748'};      Response response = await dio.get("/weather/geo", queryParameters: queryParameters);      if (response.statusCode == 200) {        print('请求成功');        var responseData = response.data.toString();        responseData = responseData.replaceAll("{", "\n{");        debugPrint('response.data=$responseData');      }    } on DioError catch (e) {      print("exception: $e");    }    return;  }

关于代理设置代码块,在Dio 2.x版本和1.x版本上设置的方式是不同的,这是因为Dio 2.x版本代码重构的原因,1.x代码上onHttpClientCreate方法放在了Dio类中,而2.x版本将该方法封装到了一个名为DefaultHttpClientAdapter的类中,Dio类中的httpClientAdapter即是默认实现了DefaultHttpClientAdapter类的对象,所以此时根据httpClientAdapter对象来设置onHttpClientCreate为自定义方法即可。

1.x版本代理设置方法的代码块如下:

Dio dio = Dio();dio.onHttpClientCreate = (HttpClient client) {  if(client == null) {    client = HttpClient();  }  client.findProxy = (url) {    return HttpClient.findProxyFromEnvironment(url, environment: {"http_proxy": 'http://192.168.124.94:8888',});  };  return client;};

拦截器

使用Dio处理网络请求可以设置拦截器,dio中定义了两个拦截器:LogInterceptorCookieManager,这两个拦截器都是抽象类Interceptor的实现,具体是对抽象类中onRequestonResponseonError三个方法的实现,我们也可以自定义拦截器处理一些自己的需求。下面使用LogInterceptor来举例说明拦截器的作用:

//在上文dio使用的代码中加入如下代码,即添加了Log拦截器dio.interceptors.add(LogInterceptor());

添加拦截器之后,执行请求,会看到控制台打印如下信息:

I/flutter (28939): *** Request ***I/flutter (28939): uri: http://v.juhe.cn/weather/geo?format=2&key=939e592487c33b12c509f757500888b5&lon=116.39277&lat=39.933748I/flutter (28939): method: GETI/flutter (28939): contentType: application/json; charset=utf-8I/flutter (28939): responseType: ResponseType.jsonI/flutter (28939): followRedirects: trueI/flutter (28939): connectTimeout: 10000I/flutter (28939): receiveTimeout: 10000I/flutter (28939): extra: {}I/flutter (28939): header: I/flutter (28939): I/flutter (28939): *** Response ***I/flutter (28939): uri: http://v.juhe.cn/weather/geo?format=2&key=939e592487c33b12c509f757500888b5&lon=116.39277&lat=39.933748I/flutter (28939): statusCode: 200I/flutter (28939): headers:I/flutter (28939):  proxy-connection: Keep-aliveI/flutter (28939):  etag: 063d270dc44003f39cf480b7ec6ff843I/flutter (28939):  content-type: application/json;charset=utf-8I/flutter (28939):  set-cookie: aliyungf_tc=AQAAAP85/D47jwIAsongemk2vUOG/ZUW; Path=/; HttpOnlyI/flutter (28939):  transfer-encoding: chunkedI/flutter (28939):  date: Sat, 02 Mar 2019 04:29:17 GMTI/flutter (28939):  I/flutter (28939): 

由打印结果可以看出LogInterceptor拦截器其实就是对request和response相关信息的打印,这有助于我们对http请求进行调试。

全局配置

由以上代码可以看出使用dio实现网络请求时,可以通过dio.options的进行全局通用配置,比如baseUrl、超时时间、请求的header信息等。

表单数据

使用post请求我们可以使用form表单的形式发送参数数据,代码如下:

Map queryParameters = {'format': '2', 'key': '939e592487c33b12c509f757500888b5', 'lon': '116.39277', 'lat': '39.933748'};Response response = await dio.post("/weather/geo", data: FormData.from(queryParameters), options: Options());

通过抓取请求包,我们会发现content-type类型如下:

请求取消

比如跳转到某个页面请求了一条远程数据,但在数据没有回来之前关闭了该页面,那这条请求是可以在关闭页面时取消掉的,这要求你在发请求时使用cancelToken参数,如下:

CancelToken _cancelToken = CancelToken();Map queryParameters = {'format': '2', 'key': '939e592487c33b12c509f757500888b5', 'lon': '116.39277', 'lat': '39.933748'};Response response = await dio.post("/weather/geo", data: FormData.from(queryParameters), cancelToken: _cancelToken);

在页面退出之前可以通过调用_cancelToken.cancel()方法取消该请求。多个请求可以使用同一个CancelToken对象,故调用该对象的cancel()方法时所有的未完成的请求均会被取消。

文件下载

Dio中实现的文件下载功能也非常简单好用,实例代码如下:

Future getSavePath() async {    Directory externalStorageDir = await getExternalStorageDirectory();    String externalStoragePath = externalStorageDir.path + "/flutterdemo";    Directory dir = Directory(externalStoragePath);    if(!dir.existsSync()) {      dir.createSync();    }    File file = File(dir.path + "/test.jpg");    if(!file.existsSync()) {      file.createSync();    }    print('file.path = ${file.path}');    return file.path;}Future _downloadImage() async {    Dio dio = Dio();    dio.options.baseUrl = "http://img.ipintu.cn/images/";    dio.interceptors.add(LogInterceptor());    String savePath = await getSavePath();    try {      Response response = await dio.download(          "/baomanwayong_04.jpg",          savePath,          onReceiveProgress: (int count, int total) {            if(total > 0) {              print((count / total * 100).toStringAsFixed(0) + "%");            }          });      if (response.statusCode == 200) {        print('下载完成');      }    } on DioError catch (e) {      print("exception: $e");    }    return;}

点击按钮调用下载方法,控制台输出信息如下:

I/flutter ( 5603): file.path = /storage/emulated/0/flutterdemo/test.jpgI/flutter ( 5603): *** Request ***I/flutter ( 5603): uri: http://img.ipintu.cn/images/baomanwayong_04.jpgI/flutter ( 5603): method: GETI/flutter ( 5603): contentType: application/json; charset=utf-8I/flutter ( 5603): responseType: ResponseType.streamI/flutter ( 5603): followRedirects: trueI/flutter ( 5603): connectTimeout: 0I/flutter ( 5603): receiveTimeout: 0I/flutter ( 5603): extra: {}I/flutter ( 5603): header: I/flutter ( 5603): I/flutter ( 5603): *** Response ***I/flutter ( 5603): uri: http://img.ipintu.cn/images/baomanwayong_04.jpgI/flutter ( 5603): statusCode: 200I/flutter ( 5603): headers:I/flutter ( 5603):  last-modified: Fri, 11 May 2018 08:45:42 GMTI/flutter ( 5603):  date: Sat, 02 Mar 2019 07:17:01 GMTI/flutter ( 5603):  x-reqid: BwAAABaE5ayYe4YVI/flutter ( 5603):  access-control-expose-headers: X-Log, X-ReqidI/flutter ( 5603):  x-m-reqid: mmcAAMu4tv7GEogVI/flutter ( 5603):  server: marco/2.8I/flutter ( 5603):  x-request-id: 8836d6cebf799bbe22c678f2c9cdb5d3; 6b3ff4ec13b9de472e4bae298d38d9c9I/flutter ( 5603):  x-log: redis.g/404;mc.g/404;redis.g;rs40_shard.sel:4/not found;rdb.g;bs.r.48.179.10783842506;DBD;v4.get;rwro.get:5;RS.dbs:5;RS:6;redis.s;redis.g;IO:42I/flutter ( 5603):  content-disposition: inline; filename="baomanwayong_04.jpg"; filename*=utf-8' 'baomanwayong_04.jpgI/flutter ( 5603):  accept-ranges: bytesI/flutter ( 5603):  content-length: 151887I/flutter ( 5603):  etag: "Fnlr7Ngb3uIdCjft615r4IJd6-BU"I/flutter ( 5603):  x-qiniu-zone: 0I/flutter ( 5603):  connection: keep-aliveI/flutter ( 5603):  cache-control: max-age=2592000I/flutter ( 5603):  access-control-allow-origin: *I/flutter ( 5603):  age: 304I/flutter ( 5603):  content-type: image/jpegI/flutter ( 5603):  access-control-max-age: 2592000I/flutter ( 5603):  x-source: C/200I/flutter ( 5603):  x-m-log: QNM:jjh1504;QNM3:80I/flutter ( 5603):  x-svr: IOI/flutter ( 5603):  content-transfer-encoding: binaryI/flutter ( 5603):  via: S.mix-sd-dst1-081, T.78.M, V.mix-sd-dst1-078, T.13.H, M.ctn-js-taz1-015I/flutter ( 5603):  x-qnm-cache: HitI/flutter ( 5603):  expires: Mon, 01 Apr 2019 07:11:57 GI/flutter ( 5603): I/flutter ( 5603): 1%I/flutter ( 5603): 8%I/flutter ( 5603): 18%I/flutter ( 5603): 29%I/flutter ( 5603): 32%I/flutter ( 5603): 33%I/flutter ( 5603): 44%I/flutter ( 5603): 45%I/flutter ( 5603): 48%I/flutter ( 5603): 54%I/flutter ( 5603): 59%I/flutter ( 5603): 69%I/flutter ( 5603): 74%I/flutter ( 5603): 76%I/flutter ( 5603): 78%I/flutter ( 5603): 79%I/flutter ( 5603): 81%I/flutter ( 5603): 82%I/flutter ( 5603): 84%I/flutter ( 5603): 100%I/flutter ( 5603): 下载完成

dio.download()方法中提供了一个回调方法onReceiveProgress可以很好的跟踪下载的进度,方便做UI上的进度展示。

写在最后

以上就是两种常用的Flutter网络请求库,Dio为我们封装了丰富的网络请求相关功能,所以Dio基本可以满足我们的日常开发需求,就不用再重复造轮子了。

dio设置自定义post请求_Flutter中的http网络请求相关推荐

  1. Python网络爬虫过程中,构建网络请求的时候,参数`stream=True`的使用

    点击上方"Python共享之家",进行关注 回复"资源"即可获赠Python学习资料 今 日 鸡 汤 海内存知己,天涯若比邻. 大家好,我是皮皮. 一.前言 前 ...

  2. [Redux/Mobx] 在Redux中怎么发起网络请求?

    [Redux/Mobx] 在Redux中怎么发起网络请求? 如果单纯的使用Redux,因为redux的actionCreator返回一个plain object,所以不能在actionCreator中 ...

  3. 计算机网络中请求超时是什么意思,网络请求超时怎么解决

    我们知道不少朋友在上网的时候,会遇到网络请求超时的情况,那造成网络请求超时的原因是什么呢?网络请求超时就是在程序默认的等待时间内没有得到服务器的响应.跟着小编一起来看看请求超时解决方法. 网络请求超时 ...

  4. android网络请求回调管理,Android HTTP网络请求的异步实现

    前言 大家都知道网络操作的响应时间是不定的,所有的网络操作都应该放在一个异步操作中处理,而且为了模块解耦,我们希望网络操作由专门的类来处理.所有网络数据发送,数据接收都有某几个类来实现,外部其它模块只 ...

  5. dio设置自定义post请求_flutter中dio的post请求方式使用总结

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,即是折腾每一天. 重要消息 1 引言 dio用来在flutter跨平台开发中访问网络的框架,在使用的时候,我们首先是引入依赖 depen ...

  6. dio设置自定义post请求_Flutter 使用dio来发起网络请求以及Cookie管理

    说点儿闲话 Flutter官方建议您使用 dio 来发起网络请求,在学习过程中,也尝试过用dart io中的HttpClient发起的请求,这里主要讲一下dio的使用以及CookieJar.Cooki ...

  7. dio设置自定义post请求_flutter Dio封装get/post请求

    最近刚学flutter,参考简书大佬们的文章,使用dio简单封装了一下网络请求工具类. 依赖版本 9683BF5F-1627-47F1-AE3A-ECBC55ED49CF.png 网络请求单例 A2F ...

  8. dio设置自定义post请求_基于dio库封装flutter项目的标准网络框架

    网络框架是每个应用的基石,封装一个好的网络框架不仅是项目的一个好的开始,并且直接影响到随后项目的稳定性和可扩展性.在移动开发的各个端都有非常赞的网络请求基础框架,比如Android的okhttp库.s ...

  9. cmd怎么使用post请求’_flutter中dio的post请求方式使用总结

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,即是折腾每一天. 重要消息 flutter中网络请求dio使用分析 视频教程在这里 Flutter 从入门实践到开发一个APP之UI基础 ...

最新文章

  1. 传递闭包(Floyd+bellman-Fold POJ1932)
  2. 不动产登记进入倒计时 哪些房子必须要卖掉?
  3. Mysql存储过程和存储函数
  4. sql查看视图字段信息_高级(视图 索引)
  5. php post undefined index,PHP 中提示undefined index如何解决(多种方法)
  6. AcWing 180. 排书
  7. 人为什么必须积极有为?
  8. c/c++ 多线程 ubuntu18.04 boost编译与运行的坑
  9. [CSS学习] line-height属性讲解
  10. 数据可视化:Metabase
  11. 并行化:你的高并发大杀器
  12. Web前端实现3D旋转魔方相册【超详细】
  13. PPT创作技巧及有用素材
  14. Vue3 + Vite 使用 Less 配置
  15. QQ、UC手机浏览器访问电脑版网页
  16. linux 模拟误码率,基于System View的比特误码率测试的仿真研究
  17. Word 边框刷使用方法
  18. 【软考四】软件知识产权基础知识(做题)
  19. BeatSaber节奏光剑插件开发官方教程1-创建一个插件模板
  20. Java fx 变速播放音乐_变速变声播放器(Impulse Media Player)

热门文章

  1. Vbox异常解决-centos下的安装
  2. 从程序员小仙飞升上神,java技术开发要如何实现?
  3. nginx + tomcat + redis 部署项目,解决session共享问题。
  4. TextView settextcolor 无效解决方案
  5. 51单片机产生1Hz-5kHz可调占空比方波
  6. hdu 3592 差分约束
  7. Bailian4018 子串【字符串】
  8. NUC1170 加农炮
  9. POJ NOI0101-09 字符菱形
  10. CCF NOI1005 存款收益