本節目標
- 同步、非同步
sync
async
- 關鍵字
await
yield
- 加上
*
的區別
視訊
程式碼
正文
在 BLOC 中常見 yield yield* Stream
計算器 Bloc 程式碼
我們可以發現在 bloc 模組中,非常多 yield*
yield
async*
,如何正確使用還是很重要的,所以這篇文章把同步、非同步的對應的操作符都整理出來。
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 可序列化物件
- 程式碼
main() {
getList(10).forEach(print);
}
Iterable<int> getList(int count) sync* {
for (int i = 0; i < count; i++) {
yield i;
}
}
複製程式碼
- 輸出
0
1
2
3
4
5
6
7
8
9
Exited
複製程式碼
- 我如果把
sync
的*
去掉,編輯器會提示這是固定格式。
同步 sync* + yield*
帶上 * 因為 yield 返回物件是 Iterable
- 程式碼
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;
}
}
複製程式碼
- 輸出
0
1
2
3
4
5
6
7
8
9
Exited
複製程式碼
- 我把
yield
的*
去掉後,提示返回Iterable<T>
必須帶上*
非同步 async + await
Future + async + await 經典配合
常見場景,等待非同步完成,比如拉取資料、 IO 操作
- 程式碼
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));
}
複製程式碼
- 輸出
start..........
0
Exited
複製程式碼
這裡就直接返回了, 沒有後續的任何操作。
非同步 async* + yield
帶上 *
後,yield 返回 Stream 物件
接收方用 listen(...)
- 程式碼
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;
}
}
複製程式碼
- 輸出
0
1
2
3
4
5
6
7
8
9
Exited
複製程式碼
- yield 必須和
async*
或sync*
配套使用
非同步 async* + yield*
yield* 後返回的是另一個 Stream 物件
- 程式碼
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;
}
}
複製程式碼
- 輸出
0
1
2
3
4
5
6
7
8
9
Exited
複製程式碼
- 返回
Stream<T>
型別必須是用yield*
的方式
© 貓哥