本节目标

  • 同步、异步 sync async
  • 关键字 await yield
  • 加上 * 的区别

视频

https://www.bilibili.com/video/BV1JZ4y1w7hX/

代码

https://github.com/ducafecat/flutter-bloc-learn/tree/master/sync-async

正文

在 BLOC 中常见 yield yield* Stream

计算器 Bloc 代码

我们可以发现在 bloc 模块中,非常多 yield* yield async* ,如何正确使用还是很重要的,所以这篇文章把同步、异步的对应的操作符都整理出来。

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
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterInitial(0));

int counterNum = 0;

@override
Stream<CounterState> mapEventToState(
CounterEvent event,
) async* {
if (event is CounterIncrementEvent) {
yield* _mapIncrementEventToState(event);
} else if (event is CounterSubductionEvent) {
yield* _mapSubductionEventToState(event);
}
}

Stream<CounterState> _mapIncrementEventToState(
CounterIncrementEvent event) async* {
this.counterNum += 1;
yield CounterChange(this.counterNum);
}

Stream<CounterState> _mapSubductionEventToState(
CounterSubductionEvent event) async* {
this.counterNum -= 1;
yield CounterChange(this.counterNum);
}
}

同步 sync* + yield

同步 sync 后返回 Iterable 可序列化对象

  • 代码
1
2
3
4
5
6
7
8
9
main() {
getList(10).forEach(print);
}

Iterable<int> getList(int count) sync* {
for (int i = 0; i < count; i++) {
yield i;
}
}
  • 输出
1
2
3
4
5
6
7
8
9
10
11
0
1
2
3
4
5
6
7
8
9
Exited
  • 我如果把 sync* 去掉,编辑器会提示这是固定格式。

同步 sync + yield

带上 * 因为 yield 返回对象是 Iterable

  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
main() {
getList(10).forEach(print);
}

Iterable<int> getList(int count) sync* {
yield* generate(count);
}

Iterable<int> generate(int count) sync* {
for (int i = 0; i < count; i++) {
yield i;
}
}
  • 输出
1
2
3
4
5
6
7
8
9
10
11
0
1
2
3
4
5
6
7
8
9
Exited
  • 我把 yield* 去掉后,提示返回 Iterable<T> 必须带上 *

异步 async + await

Future + async + await 经典配合

常见场景,等待异步完成,比如拉取数据、 IO 操作

  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
main() {
print("start..........");
getList(10).then(print);
}

Future<int> getList(int count) async {
await sleep();
for (int i = 0; i < count; i++) {
return i;
}
return 99;
}

Future sleep() async {
return Future.delayed(Duration(seconds: 3));
}
  • 输出
1
2
3
start..........
0
Exited

这里就直接返回了, 没有后续的任何操作。

异步 async* + yield

带上 * 后,yield 返回 Stream 对象

接收方用 listen(…)

  • 代码
1
2
3
4
5
6
7
8
9
10
main() {
getList(10).listen(print);
}

Stream<int> getList(int count) async* {
for (int i = 0; i < count; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
  • 输出
1
2
3
4
5
6
7
8
9
10
11
0
1
2
3
4
5
6
7
8
9
Exited
  • yield 必须和 async*sync* 配套使用

异步 async + yield

yield* 后返回的是另一个 Stream 对象

  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
main() {
getList(10).listen(print);
}

Stream<int> getList(int count) async* {
yield* generate(count);
}

Stream<int> generate(int count) async* {
for (int i = 0; i < count; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
  • 输出
1
2
3
4
5
6
7
8
9
10
11
0
1
2
3
4
5
6
7
8
9
Exited
  • 返回 Stream<T> 类型必须是用 yield* 的方式

© 猫哥

https://ducafecat.tech

https://ducafecat.gitee.io