Dart是一个单线程语言,能够理解成物理线路中的串联,当其遇到有延迟的运算(好比IO操做、延时执行)时,线程中按顺序执行的运算就会阻塞,用户就会感受到卡顿,因而一般用异步处理来解决这个问题。编程
Dart异步编程有两种方式:Future和Streamjson
Future至关于40米大砍刀,Stream至关于一捆40米大砍刀。dart提供了关键字async(异步)和await(延迟执行),至关于普通的便捷的小匕首,而小匕首是咱们平时常常用到的。api
当遇到有须要延迟的运算(async)时,将其放入到延迟运算的队列(await)中去,把不须要延迟运算的部分先执行掉,最后再来处理延迟运算的部分。app
async await 这两个关键字是dart语言的特性,能让你写出看起来像是“同步”的“异步”代码,先看一个方法案例:异步
/*HTTP的get请求返回值为Future<String>类型,即其返回值将来是一个String类型的值*/ /*async关键字声明该函数内部有代码须要延迟执行*/ getData() async { /*await关键字声明运算为延迟执行,而后return运算结果*/ return await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"}); }
而后咱们尝试调用这个方法,并获取返回值。async
String data = getDate();
而后控制台报错了….ide
为何呢?由于data是String类型,而函数getData()是一个异步操做函数,其返回值是一个await延迟执行的结果。在Dart中,有await标记的运算,其结果值都是一个Future对象,Future不是String类型,因此就报错了。异步编程
总结一下:函数
在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。url
还有两点须要注意:
就是说:
1.要想 return await … ,那么方法首先是 async 的,如上方方法。
2.使用 async 标注的方法,必需要用 await 接收返回值,好比上方方法在接收返回值时,须要加入 await
var data = await getData();
Future表示一件“未来”会发生的事情,未来能够从Future中取到一个值。当一个方法返回一个Future的事情,发生两件事情:
要取到这个“返回值”,有两种方式:
咱们看这两种实现方式的案例:
先看个案例,等待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),因此可让咱们的程序“看起来”是顺序执行的。
咱们修改一下 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这个方法。
在请求方法中直接 return await .. .的时候,实际上返回的是一个延迟计算的Future对象。
有两点须要注意:
Flutter 中有两种实现异步编程的方式:Future api、 async await
平常开发中经常使用的是 async await Future 搭配。