ビルド後の処理でwidget
をレンダリングしてからアクセスするにはTimer
で関数を呼び出してもいいのですがawait
を入れたい場合はいくつかの方法があり、
Future(() { /* FutureのAPIかasync/awaitを使う */ });
// mainを抜けた時点で実行されるのがmicrotask、useEffect内でasync/awaitを使用したい時など
Future.microtask(() { /* 処理内容 */ });
// 遅延処理
Future.delayed(Duration.zero, () { /* 処理内容 */ });
Future
/Future.microtask
/Future.delayed
を利用するか、
// riverpod更新時にNavigator.of(context).pushで処理が衝突する現象を回避
WidgetsBinding.instance.addPostFrameCallback((_) { /* 処理内容 */ });
// import package:flutter/scheduler.dart; が必要
// WidgetsBindingと同様の処理
SchedulerBinding.instance.addPostFrameCallback((_) { /* 処理内容 */ });
// import 'dart:async';
scheduleMicrotask(() { /* 処理内容 */ });
WidgetsBinding
/SchedulerBinding.instance.addPostFrameCallback
/scheduleMicrotask
などがあります。
どれを利用しても上手く動いてくれますが、よく目につくのはFuture.delayed
です。
実行までのcontext
やwidget
のビルドを保証して次のアクセスを円滑にしてくれます。Flutter
内部の問題を処理しながら動いてくれるのは後者の方ですが、見やすさで前者を利用される方が多いような気がします。
それぞれの動きを検証
import 'dart:async';
void main() async{
print('1');
await Future((){
print('2');
Future(()=>print("3"));
scheduleMicrotask(() => print('4'));
Future.microtask(()=>print("5"));
new Future.delayed(new Duration(seconds:1),
() => print('6'));
new Future(() => print('7'));
new Future(() => print('8'));
print('9');
});
scheduleMicrotask(() => print('10'));
print('11');
}
// 1 2 9 11 4 5 10 3 7 8 6
Future.delayed
でループしている動き
import 'dart:async';
Future<void> main() async {
int _count = 0;
// 3秒ごとにカウントして行き、3回目に終了
while(true) {
await Future.delayed(Duration(seconds: 3));
_count++;
print("$_count回");
if (_count == 3) {
break;
}
}
}