非同期を含めた処理を書いていると、非同期処理が完了してから、メインの処理を続けたいときがある。もしくは、非同期処理の結果を、メインの処理に表示したいときがある。そんなときに、Completerが役に立つ。
実際に使ったこと
私が実際にCompleterを使った一例は、以下の通りです。
- 3つの音を連続して再生させるために、それぞれの音の完了時に、次の音の開始前にCompleterで待機した
- Firestoreから取得したデータを画面に表示するため、データ取得まで画面描画を待機させ、取得後に表示項目に初期値を渡した
ソース
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
void main() async {
test('completer', () async {
Completer completer = Completer();//2
List result = [];
// 1
Future.delayed(const Duration(seconds: 1)).then((value) {
result.add('delayed');
expect(completer.isCompleted, false);
completer.complete('delay finished');//3
expect(completer.isCompleted, true);
});
result.add('before future');
result.add(await completer.future); //4
result.add('after future');
expect(result.length, 4);
expect(result[0], 'before future');
expect(result[1], 'delayed');
expect(result[2], 'delay finished');
expect(result[3], 'after future');
});
}
- Future.delayed
- Completer completer = Completer()
- completer.complete
- await completer.future
- completer.isCompleted
実際には、メインの処理の前に実施したい同期処理を記載してください。
Completerを定義します。ジェネリックで、結果に何の値を入れたいか決めてください。
結果を引数にして、Completerの処理を完了させてください。
Completer.futureでFuture型を返します。Future型をそのまま戻して、もっと後の処理で使うこともできます。ここでは、await を使って非同期処理が完了するのを待ってから、メインの処理の続きを行うようにしてます。
Completerの処理が完了しているか、まだ処理中かを取得することができます。
まとめ
そんなわけで、Completerの説明をしました。最初、音の連続再生時に使用しました。そのときは、音の再生が完了したらイベントが発生する、という処理内にCompleter.completeを入れなければなりませんでした。しかし、非同期処理やCompleterがよく分かっていなかったので、3つの音が同時に鳴らしたり、音のイベント周りもよく分からず、苦労しました。
この記事を読んだ方のお役に立てれば幸いです。役に立ってSNSにシェアしていただけると、非常に喜びます!