抛出问题:
下面这段代码:
void _test() {
print(1);
Timer.run(() {
print(2);
});
print(3);
}
打印顺序是 1 3 2.
如何让它打印 1 2 3?
解决方案:
在 iOS 开发中,信号量 Semaphore
可以很好的解决这个问题。
但是 Flutter 里没有 Semaphore
,怎么办?
Completer
可以满足你:
void _test() async {
print(1);
Completer<void> completer = Completer();
Timer.run(() {
print(2);
completer.complete();
});
await completer.future;
print(3);
}
看到没有,连使用方式都有 iOS Semaphore
的味道:
await completer.future
可以看做等待信号;completer.complete()
可以看做发送信号。
运用场景:
当我们想在异步方法的 then
回调里做一些处理,并且像写同步代码一样写异步代码的时候,可以考虑 Completer
:
Future<int> _loadData() {
return Future.delayed(const Duration(seconds: 1), () {
return 1;
});
}
Future<void> _test1() async {
const a = 2;
final b = await _loadData();
final c = a + b;
log(c.toString()); // 3
}
Future<void> _test2() async {
const a = 2;
var b = 0;
final completer = Completer();
_loadData().then((value) {
log('请求完成');
b = value;
completer.complete();
});
await completer.future;
final c = a + b;
log(c.toString()); // 3
}
上面的 test1
和 test2
实现的效果一样,都是等待 _loadData
完成后,将结果相加。
底层原理:
通过上面的例子可以发现使用 Completer
的代码并不多,就三句:
- 初始化:
final completer = Completer();
- 等待:
await completer.future;
- 完成:
completer.complete();