饿补一下Flutter中Http请求的异步操作。

Dart是一个单线程语言,可以理解成物理线路中的串联,当其遇到有延迟的运算(比如IO操作、延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感觉到卡顿,于是通常用异步处理来解决这个问题。

Dart异步编程有两种方式:Future和Stream

Future相当于40米大砍刀,Stream相当于一捆40米大砍刀。dart提供了关键字async(异步)和await(延迟执行),相当于普通的便捷的小匕首,而小匕首是我们平时经常用到的。

当遇到有需要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不需要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。

1、async和await

async await 这两个关键字是dart语言的特性,能让你写出看起来像是“同步”的“异步”代码,先看一个方法案例:

  /*HTTP的get请求返回值为Future<String>类型,即其返回值未来是一个String类型的值*//*async关键字声明该函数内部有代码需要延迟执行*/getData() async {    /*await关键字声明运算为延迟执行,然后return运算结果*/return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"}); }

然后我们尝试调用这个方法,并获取返回值。

String data = getDate();

然后控制台报错了….

为什么呢?因为data是String类型,而函数getData()是一个异步操作函数,其返回值是一个await延迟执行的结果。在Dart中,有await标记的运算,其结果值都是一个Future对象,Future不是String类型,所以就报错了。

总结一下:

在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。

还有两点需要注意:

  • await关键字必须在async函数内部使用
  • 调用async函数必须使用await关键字

后面两点怎么讲?

  1. 要想 return await … ,那么方法首先是 async 的,如上方方法。
  2. 使用 async 标注的方法,必须要用 await 接收返回值,比如上方方法在接收返回值时,需要加入 await ,var data = await getData();

2、什么是Future

Future表示一件“将来”会发生的事情,将来可以从Future中取到一个值。当一个方法返回一个Future的事情,发生两件事情:

  • 这个方法将某件事情排队,返回一个未完成的Future
  • 当这件事情完毕之后,Future的状态会变成已完成,这个时候就可以取到这件事情的返回值了。

要取到这个“返回值”,有两种方式:

  • 使用async配合await
  • 使用Future提供的api

我们看这两种实现方式的案例:

2.1、使用async配合await

先看个案例,等待3秒后返回‘我是用户’:

/*模拟异步加载用户信息*/
Future _getUserInfo() async{await new Future.delayed(new Duration(milliseconds: 3000));return "我是用户";
}/*加载用户信息,顺便打印时间看看顺序*/
Future _loadUserInfo() async{print("_loadUserInfo:${new DateTime.now()}");print(await _getUserInfo());print("_loadUserInfo:${new DateTime.now()}");
}

我们在initState中调用该方法:

@override
void initState(){print("initState:${new DateTime.now()}");_loadUserInfo();print("initState:${new DateTime.now()}");super.initState();
}

打印结果如下:

I/flutter ( 1802): initState:2019-06-20 09:46:40.097339
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:46:40.103542
I/flutter ( 1802): Instance of 'Future<dynamic>'
I/flutter ( 1802): initState:2019-06-20 09:46:40.108510
I/flutter ( 1802): 我是用户
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:46:43.117136

what?

很明显,打印结果并没有按照串联的方式依次打印。

flutter中会改造带asyc关键字的方法,让这个方法脱离主流程,变成“后面一点”执行(通过scheduleMicrotask),所以可以让我们的程序“看起来”是顺序执行的。

2.2、Future api

我们修改一下 loadUserInfo() 方法:

/*加载用户信息,顺便打印时间看看顺序*/Future _loadUserInfo() async{print("_loadUserInfo:${new DateTime.now()}");_getUserInfo().then((info){print(info);});print("_loadUserInfo:${new DateTime.now()}");}

再次运行输出一下:

I/flutter ( 1802): initState:2019-06-20 09:50:32.488765
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:50:32.494751
I/flutter ( 1802): _loadUserInfo:2019-06-20 09:50:32.499725
I/flutter ( 1802): Instance of 'Future<dynamic>'
I/flutter ( 1802): initState:2019-06-20 09:50:32.499970
I/flutter ( 1802): 我是用户

两次输出是有不同的,主要不同在于第二个 loadUserInfo 的日志打印,与‘我是用户’的输出顺序,为什么有差异?

await会阻塞流程,等待紧跟着的的Future执行完毕之后,再执行下一条语句,而如果用了Future.then这个api,那么就不会等待,直接执行下面的语句,等Future执行完了,再调用then这个方法。

3、总结

在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。

有两点需要注意:

  • await关键字必须在async函数内部使用
  • 调用async函数必须使用await关键字

Flutter 中有两种实现异步编程的方式:Future api、 async await

日常开发中常用的是 async await Future 搭配。

flutter中的异步机制Future相关推荐

  1. 跟着 Event loop 规范理解浏览器中的异步机制

    原文发自我的 GitHub blog,欢迎关注 前言 我们都知道 JavaScript 是一门单线程语言,这意味着同一事件只能执行一个任务,结束了才能去执行下一个.如果前面的任务没有执行完,后面的任务 ...

  2. html js异步绑定,JavaScript异步机制介绍

    异步就是代码执行的顺序,并不是按照从上到下的顺序一次性执行,而是在不同的时间段执行,一部分代码在"未来执行".本文就来为大家介绍一下JavaScript中的异步机制. 单线程异步执 ...

  3. js异步等待完成后再进行下一步操作_彻底搞懂JS事件中的循环机制 Event Loop

    我们都知道JavaScript是单线程语言,就是因为单线程的特性,就不得不提js中的同步和异步 一.同步和异步 所谓单线程,无非就是同步队列和异步队列,js代码是自上向下执行的,在主线程中立即执行的就 ...

  4. Flutter第一部分(UI)第六篇:一文搞懂Flutter中的资源引用机制

    前言:Flutter系列的文章我应该会持续更新至少一个月左右,从User Interface(UI)到数据相关(文件.数据库.网络)再到Flutter进阶(平台特定代码编写.测试.插件开发等),欢迎感 ...

  5. 详解Flutter中各种Binding

    前言 Flutter中所有的运转都是在各种Binding中调度的,也正是这些绑定器的存在彻底解耦了Widget . Element .RenderObject 对 Platform端的依赖,阅读此文需 ...

  6. flutter中compute和isolate

    async和await: 对于普通的任务,使用async和await可实现异步处理任务,而async的处理方式并非使用的是多线程,而是依然在UI线程中处理任务,是在同一个线程上的并发操作. 对于比较繁 ...

  7. FLutter入门:异步加载组件FutureBuilder

    FutureBuilder 在实际开发中,进入一个页面后执行网络请求加载数据并显示是非常普遍的,这时候我们一般会显示loading直到加载完成显示正常页面.在flutter中我们可以在initStat ...

  8. Flutter中如何利用StreamBuilder和BLoC来控制Widget状态

    参考文章:Reactive Programming - Streams - BLoC (为了便于阅读,略去了原文中的一些跟StreamBuilder和Bloc无关的拓展概念,比如RxDart.Demo ...

  9. Flutter中的点击、拖动和其它手势

    Flutter中的点击.拖动和其它手势 介绍 Pointers 手势 手势消歧 介绍 本文档介绍了如何在Flutter中监听并响应手势(点击.拖动和缩放). Flutter中的手势系统有两个独立的层. ...

最新文章

  1. LVS负载均衡之ipvsadm部署安装(安装篇)
  2. 解决Chrome浏览器启动速度慢的问题
  3. PowerShell攻防进阶篇:nishang工具用法详解
  4. 圆形渐变shader_Flutter 中渐变的高级用法
  5. java静态成员方法_java的静态成员、静态方法的注意事项!
  6. 中国5G研发试验喜迎“小学课本”
  7. matplotlib.pyplot.bar()条形图
  8. 【转载】强大的MongoDB数据库管理工具
  9. 思科修复 ASA/FTD 防火墙高危缺陷,已遭利用
  10. UVA10293 Word Length and Frequency【单词长度频度+strtok】
  11. 国产服务器虚拟化产品,国内主流虚拟化厂商之间比较.doc
  12. win10录屏_一分钟教你学会两种电脑录屏的方法,以后别再说不知道了
  13. flickr网站用到的php技术
  14. jboot websocket的使用
  15. 撩妹代码html,Web前端
  16. 最优秀好用的免费文件压缩/解压缩工具软件 (可替代WinRAR与7-Zip)——Bandizip
  17. SQL判断某列中是否包含中文字符或者英文字符
  18. 常见排序算法的最好、最坏、平均时间复杂度以及空间复杂度
  19. 虚拟机迁移技术漫谈(转)
  20. 酒精测试仪方案开发解析

热门文章

  1. [html] 对于写一个页面布局,html/css/js这三者你是先写哪个后写哪个?
  2. 工作341:uni-表头不显示
  3. [js] innerHTML与outerHTML有什么区别?
  4. 前端学习(2553):内容概述
  5. 前端学习(2242)以组件方式创建UI
  6. 前端学习(1867)vue之电商管理系统电商系统之登录退出实现表单的重置
  7. 前端学习(1657):前端系列实战课程之文字输入框实现思路
  8. 前端学习(715):数组新增元素
  9. 第八十期:初创公司5大Java服务困局,阿里工程师如何打破?
  10. Git(2):安装和使用