Flutter 假异步的实现示例
就像 android 有 handle 一样,消息队列这东西好像还真是系统必备,Flutter 也有自己的消息队列,只不过队列直接封装在了 Dart 的线程类型 Isolate 里面了,不过 Flutter 还是提供了 Futrue 这个 API 来专门来操作各种消息,以及实现基于消息队列的假异步
Flutter 的“异步”机制
这里的异步是加了引号的,可见此异步非真异步,而是假异步。Flutter 的 异步 不是开新线程,而是往所属线程的 消息队列 中添加任务,当然大家也可以按上文那样自己展开真异步操作
Flutter 对代码分2类: 同步代码和异步代码
- 同步代码:传统一行行写下来,一行行执行的代码
- 异步代码:通过 Future API 把任务添加到 Isolate 所属消息队列执行的伪异步
- 执行顺序:先运行同步代码,再运行异步代码
为啥,很明显啊,异步代码是往消息队列里添加任务,那肯定得等现在的代码运行完了,线程有空闲了才能开始执行消息队列里的任务呀~
举个例子:
void test() { print("AA"); Future(() => print("Futrue")); print("BB"); } ~~~~~~~~~~~log~~~~~~~~~~~~~ I/flutter (10064): AA I/flutter (10064): BB I/flutter (10064): Futrue
print("Futrue")) 任务等到最后才执行的...
Flutter 提供了往 消息队列 添加数据的 API: Future
往 MicroTask 队列添加任务
scheduleMicrotask((){ // ...code goes here... }); new Future.microtask((){ // ...code goes here... });
往 Event 队列添加任务
new Future(() { // ...code goes here... });
Future 的基本使用
Future 对象是 Flutter 专门提供的,基于消息队列实现异步的类,Future 对象会把自身当做一个任务添加到消息队列中去排队执行
Future 对象接受的是一个函数,就是要执行的任务,用 () => ... 简写也是可以的
void task() { print("AA"); } var futrue = Future(task);
创建 Future 任务方式:
- Future()
- Future.microtask()
- Future.sync() - 同步任务
- Future.value()
- Future.delayed() - 延迟xx时间添加任务
- Future.error() - 错误处理
我们来看几个代表性的:
Future.sync() - 阻塞任务,会阻塞当前代码,sync 的任务执行完了,代码才能走到下一行
void test() { print("AA"); Future.sync(() => print("Futrue")); print("BB"); } ~~~~~~~~~~~~log~~~~~~~~~~~~~~ I/flutter (10573): AA I/flutter (10573): Futrue I/flutter (10573): BB
Future.delayed() - 延迟任务,指定xx时间后把任务添加到消息队列,要是消息队列前面有人执行的时间太长了,那么执行时间点就不能把握了,这点大家要知道
void test() { print("AA"); Future.delayed(Duration(milliseconds: 500),() => print("Futrue")); print("BB"); } ~~~~~~~~~~~~log~~~~~~~~~~~~~~ I/flutter (10573): AA I/flutter (10573): BB I/flutter (10573): Futrue
Future 的链式调用
Future 也支持链式调用的,在 API 使用上也是很灵活的,提供了下面的选择给大家
.then - 在 Future 执行完后执行,相当于一个 callback,而不是重新创建了一个 Future
Future.delayed(Duration(seconds: 1),(){ print(("AAA")); return "AA"; }).then((value){ print(value); });
.catchError - future 不管在任何位置发生了错误,都会立即执行 catchError
Future.delayed(Duration(seconds: 1),(){ throw Exception("AAA"); }).then((value){ print(value); }).catchError((error){ print(error); });
.whenComplete - 不管是否发生异常,在执行完成后,都会执行该方法
Future.delayed(Duration(seconds: 1),() { throw Exception("AAA"); }).then((value) { print(value); }).catchError((error) { print(error); }).whenComplete(() { print("complete..."); });
.wait - 可以等待所有的 future 都执行完毕再走 then 的方法
Future.wait([ // 2秒后返回结果 Future.delayed(new Duration(seconds: 2),() { return "hello"; }),// 4秒后返回结果 Future.delayed(new Duration(seconds: 4),() { return " world"; }) ]).then((results) { print(results[0] + results[1]); }).catchError((e) { print(e); });
大家想想啊
Futrue() .then() .then() ...
这样的链式写法不就是标准的去 callback 回调地狱的方式嘛
async/await 关键字
async/await 这组关键字是系统提供的另一种实现 异步 任务的 API, async/await 底层还是用 Futrue 实现的,从使用上看是对 Futrue 的简化,本质上还是基于 消息队列 实现的异步,是 假异步 ,和 Isoalte 是不一样的
async/await 的特点就是: 成对出现
- async - 修饰方法,用 async 声明的方法都是耗时的
- await - 调用 async 方法时使用,也可以在 async 方法内部是适用,await 表示阻塞,下面的任务必须等 await 调用的方法执行完之后才能执行
比如这样:
anysncTest() async { print("async 休眠 start..."); sleep(Duration(seconds: 1)); print("async 休眠 end..."); } await anysncTest();
本质上 await 调用的方法其实是把这个方法包装到 Futrue 中去消息队列里执行,只不过是: Future.sync() 阻塞式的 Future 任务
这 async 在布局中也是可以直接用的
class TestWidgetState extends State<TestWidget> { int _count = 0; @override Widget build(BuildContext context) { return Material( FlatButton( onPressed: () async { _count = countEven(1000000000); setState(() {}); },child: Text( _count.toString(),)),); }
async/await 是阻塞式的函数
实验1:
// 这是异步任务代码 aaa() async{ print("main1..."); await anysncTest(); print("main2..."); print("main3..."); } anysncTest() async { print("async 休眠 start..."); sleep(Duration(seconds: 1)); print("async 休眠 end..."); } // 点击按钮去执行 Widget build(BuildContext context) { return RaisedButton( child: (Text("click!")),onPressed: () async { await aaa(); },); }
以上是来客网为你收集整理的Flutter 假异步的实现示例全部内容,希望文章能够帮你解决Flutter 假异步的实现示例所遇到的程序开发问题。
如果觉得来客网网站内容还不错,欢迎将来客网网站推荐给程序员好友。