Future

等待异步

有时候执行某个动作,需要等到另一个事件结束,可以用Completer类。

常见的有:

执行某个动作,需要弹窗等待用户选择某条件后再执行后续代码,

//事例

var c = Completer<bool>();

Dialogs.tipsCard(title, tip,
  failMsg: '',
  actions: [i18n.ok],
  callback: (index) => c.complete(true),
  dismissCallBack: () {
    if (!c.isCompleted)
      c.complete(false);
  },
);

return c.future;

其他:

Completer

Completer允许你做某个异步事情的时候,调用c.complete(value)方法来传入最后要返回的值。最后通过c.future的返回值来得到结果,(注意:宣告完成的complete和completeError方法只能调用一次,不然会报错)。看下面的例子更容易理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
test() async {
Completer c = new Completer();
for (var i = 0; i < 1000; i++) {
if (i == 900 && c.isCompleted == false) {
c.completeError('error in $i');
}
if (i == 800 && c.isCompleted == false) {
c.complete('complete in $i');
}
}

try {
String res = await c.future;
print(res); //得到complete传入的返回值 'complete in 800'
} catch (e) {
print(e);//捕获completeError返回的错误
}
}

怎么将一个Callback回调转化成Future同步方法(Callback to Future),可以配套async / await去使用呢?

使用场景:dio请求使用call,但外部基本还是习惯使用future方式,为了减少接口的改动,使用callback转future方式。

参考文章:Flutter&Dart Callback转Future

compute

在一个页面中做耗时比较大的运算时,就算用了async / await异步处理, ui页面的动画还是会卡顿,因为还是在这个UI线程中做运算,异步只是说我可以先运行其他的,等我这边有结果再返回,但是,记住,我们的计算仍旧是在这个UI线程,仍会阻塞UI的刷新,异步只是在同一个线程的并发操作。

要解决这个卡顿问题,可以把运算移到另一个线程中,在dart中,这里不是称呼线程,是Isolate,直译叫做隔离,是因为隔离不共享数据,每个隔离中的变量都是不同的,不能相互共享。

Isolate的操作比较复杂,dart中封装了一层简单的实现

1
2
/// package:flutter/foundation.dart
Future<R> Function<Q, R>(FutureOr<R> Function(Q), Q, {debugLabel: String})compute

使用方法

1
2
3
4
5
6
7
8
import 'package:flutter/foundation.dart';

function callback( val ){
...
return res
}
/// `callback` 必须是顶级方法或者是类的静态方法
var res = await compute( callback , val );

简单来讲就是运行var res = await compute( callback , val )函数。callback的传入参数是val, return的数据就是callback的res;

使用场景

  • 方法执行在几毫秒或十几毫秒左右的,应使用Future
  • 如果一个任务需要几百毫秒或之上的,则建议compute(只有一次返回)或Isolate(用于订阅或有多次返回的)

Flutter/Dart :如何在app启动前等待异步任务?

我在一个dart应用程序上工作,我想获取缓存(SharedPreferences)中存在的数据,然后在应用程序的UI (主屏幕)上显示它。

问题:由于SharedPreferences是一个等待调用,我的主页加载,试图读取数据,应用程序崩溃,因为还没有从SharedPreferences中获取数据,并且应用程序在此之前加载。

其他参考文章:

多任务

dart笔记13:用future实现等待多个任务完成后,再得到所有的执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import 'dart:async';

void main() {
print('start');

Future task1 = Future(() {
print('task1');
return 1;
});

Future task2 = Future(() {
print('task2');
return 2;
});

Future task3 = Future(() {
print('task3');
return 3;
});

Future future = Future.wait([task1, task2, task3]);

future.then((value) {
print(value);
}).catchError((e){

});


print('end');

//执行结果:
//start
//end
//task1
//task2
//task3
//[1, 2, 3]
}

FutureBuilder

Flutter:使用 Completer 实现自定义任务队列