【Flutter】WidgetsBinding.instance.addPostFrameCallbackについてシンプルに解説!

Flutter状態管理

FlutterにおいてWidgetsBinding.instance.addPostFrameCallbackを使用することが時々あります。

今回はそちらの使用方法やメリット、注意点についてまとめました。addPostFrameCallbackについて深く知りたい・そもそもどういうものだっけ?・どうやって使うのと感じている方にシェアできれば幸いです。

WidgetsBinding.instance.addPostFrameCallbackとは

addPostFrameCallbackにおいて下記2点が重要です。

重要な2点

  • コールバックを登録できる
    • 現在のフレームのレンダリングが完了した後に登録
      • UIが完全に描画された後に追加の処理を行いたい場合に便利
      • 例: アニメーションの開始、初期化完了後の操作
  • 一回だけ呼び出されるコールバック
    • 効率的なパフォーマンスを可能に
      • フレーム間のタイミングを制御することで
      • 不要な再描画や処理を避けられる

可能になること

  • ウィジェットツリーが完全に構築された後に、特定の処理を実行できる
    • ウィジェットのビルドが完了し、フレームが描画された後にコールバックを実行
    • 必要な状態が確実に初期化されたタイミングで処理を実行できる

使い方

今回はFlutterflutter_hooksを使ってuseEffect内で何か処理をしたい場合の例でやってみます。

通常のuseEffect

通常は、下記の通りで、中に初回で呼びたいものや特定の値が変化したときに呼びたい処理を記載します。詳しくは下記の記事でも解説していうので参考にしてみてください。

  useEffect(() {
      // なんらかの処理
      return;
    }, []);

addPostFrameCallback使用のuseEffect

下記のように、新しいページをダイアログで呼びたい場合などにaddPostFrameCallbackを使うことでダイアログを呼び出せます。

    useEffect(() {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        showTestDialog();
      });
      return;
    }, []);

  // ダイアログを呼び出す関数
    void showTestDialog() {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return const TestPage();
        },
      );
    }

エラーパターン

そのままでダイアログを出そうとすると下記のようなエラーが表示されます。

Cannot listen to inherited widgets inside HookState.initState. 
Use HookState.build instead
HookState.initState 内で継承されたウィジェットをリッスンできません。
代わりに HookState.build を使用してください。

addPostFrameCallbackでラップすることで使用可能になりますが、下記のように直接呼ぼうとするとエラーになります。

    useEffect(() {
      // addPostFrameCallbackでラップしないとエラーが発生する
        showTestDialog();
      return;
    }, []);

こちらエラーについては別途解説しているのでそちらもよかったらご覧ください。

addPostFrameCallbackの注意

使い方の注意として以下の2つに気をつけてください。

  • コールバックの実行タイミング
    • 実行タイミングは「そのフレームのレンダリングが完了した後」
      • ウィジェットの build メソッドや initState 内で行う初期化処理とは違う
      • フレームが「完全に描画された後」のタイミングで処理を追加する場合が🙆
  • 頻繁に使用するのは注意
    • 多用するとパフォーマンスに悪影響を与える場合がある
      • 大量のコールバックを登録する
      • レンダリング後の負荷が増える可能性があります。

参考記事

最後に

簡単ではございますが、WidgetsBinding.instance.addPostFrameCallbackについてまとめてみました。また、Flutterの状態管理やHooks等についても発信できたらと思います。

ではまた。

コメント

タイトルとURLをコピーしました