Flutter开发者

Dart中的异步操作

2018-04-12

上期回顾

在前面的文章中我们很多次提到了Future这个东西,这个单词翻译过来的意思是‘未来’的意思。在flutter中它表示一个未来某些时候返回数据的一个对象。

借助Future我们可以在Flutter实现异步操作,今天我们就来正式了解下Future。

为什么要用异步

首先我们知道Dart这门语言是单线程的。同步代码的执行会让我们的程序处于过长时间的等待状态终止ANR。

对于耗时的操作(I/O、网络操作等)我们必须要使用异步来处理它们,只有这样,才不会因为这些耗时的操作来影响程序的正常运行。

比如说我们去餐馆吃饭,在等餐的过程中我们一边和朋友聊天,一边玩手机。这个场景用代码表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void main() {

print( enterRestaurant());
print( waitForDinner());
print( startChat());
print( playPhone());
}

String enterRestaurant(){
return "和朋友进入了一家餐馆";
}
String waitForDinner(){
return "我们的菜来了,我要开始吃饭了";
}
String startChat(){
return "我们朋友聊起家常";
}
String playPhone(){

return "等了好好久了,我还是玩会手机吧";
}

运行下,看下控制台输出:

和朋友进入了一家餐馆

我们的菜来了,我要开始吃饭了

我们朋友聊起家常

等了好好久了,我还是玩会手机吧

从逻辑来看我们确实是先进入了餐馆,然后等待菜来,等的期间开始了聊天和玩手机。但是因为Dart是单线程的所以无论你等待饭来的时间多长,在这个操作没有完成之前他都不会去执行下面的操作,这样就不美好了啊,我在等吃饭的时间内什么也做不了了啊。

上面的例子就是非异步操作引起的问题。在Flutter要想解决上面的问题可以借助于Future来解决这个问题

下面我们就来看看什么是Future

什么是Future

Future是在未来某个时间获得想要对象的一种手段。

当调用Future后系统会将使用Future的操作放入一个队列中去排队执行,并返回一个未完成的Future对象,当事件完成后或者有一个可用的值时Future就会调用自己的then回调让调用者去处理这个对象。

在Flutter中我们可以使用如下两种方式来获取Future。

  1. 使用Future APi
  2. 使用async和await (Dart1.9后支持)

还是以上面的场景为例,我们先借助于Future APi来实现异步效果。

首先我们需要自己声明一个属于我们的Future对象。

1
2

Future<String> waitDinnerFuture=new Future(waitForDinner);

我们个Future传入了我们需要的返回值类型String并且将我们需要耗时操作的函数传递给了Future,这样我们就可以获得一个Future对象。

在Future Api中我们可以使用

waitDinnerFuture.then((str){});接收上层返回可用的值

waitDinnerFuture.whenComplete((){});事件完成回调

waitDinnerFuture.catchError((error){});事件错误的捕获

waitDinnerFuture.timeout(new Duration(microseconds: 30));超时时间

好吧,也非常的简单,那么我就试下效果哈。

1
2
3
4
5
6
7
8

print(enterRestaurant());
Future<String> waitDinnerFuture=new Future(waitForDinner);
waitDinnerFuture.then((str){
print(str);
});
print( startChat());
print( playPhone());

可以看到,在调用的地方吧我们只是处理了下调用等待吃饭的过程,其他的操作还是按照原来的去执行,在这里我们仅仅调用了then方法。来看下控制台输出。

和朋友进入了一家餐馆

我们朋友聊起家常

等了好好久了,我还是玩会手机吧

我们的菜来了,我要开始吃饭了

这样的话我们就可以在等餐的同时愉快的玩耍了。

试一下 async

同样的我们也可以借助于async和await来获取一个Future对象。

首先我们需要使用async来修饰需要异步处理的方法上,然后使用await来修饰需要异步操作的地方,然后 这个函数就可以返回一个Future对象了。

1
2
3
4
5
6
7
8
9
10
void main() {

print(enterRestaurant());
Future<String> waitDinnerFuture= waitForDinner();
waitDinnerFuture.then((str){
print(str);
});
print( startChat());
print( playPhone());
}

同样的我们来看下控制台的输出

和朋友进入了一家餐馆

我们朋友聊起家常

等了好好久了,我还是玩会手机吧

我们的菜来了,我要开始吃饭了

Future的其他用法

考虑三个功能expensiveA(),expensiveB()以及expensiveC()都返回Future对象

使用then()链接函数调用

当Future-returning函数需要按顺序运行时,请使用链式then() 调用:

1
2
3
4
5

expensiveA()
.then((aValue) => expensiveB())
.then((bValue) => expensiveC())
.then((cValue) => doSomethingWith(cValue));

等待多个Future以完成使用Future.wait()

如果功能的执行顺序不重要,可以使用 Future.wait()。

这些功能快速连续触发; 当他们都完成一个价值,Future.wait()返回一个新的未来。这个未来完成了包含每个函数产生的值的列表。

1
2
3
4
Future
.wait([expensiveA(), expensiveB(), expensiveC()])
.then((List responses) => chooseBestResponse(responses))
.catchError((e) => handleError(e));

具体怎么使用还需要大家在用到的时候看下就好了。

小结

  • Dart是单线程的变成语言
  • 使用Future可以是同步操作异步化
  • Future可以使用async和await来回去
  • Future可以处理链式调用和多个Future同时返回结果
Tags: 异步
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

打赏请备注姓名或者昵称,方便我后期统计哦

关注公众号,及时查阅最新文章