🥯

addPostFrameCallback methodはどんな時に使うのか?

2023/10/21に公開

Overview

https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html

このフレームの終わりにコールバックをスケジュールします。

提供されたコールバックは、フレームの直後、永続フレーム コールバックの直後 (メインのレンダリング パイプラインがフラッシュされたとき) に実行されます。

このメソッドは新しいフレームを要求しません。 フレームがすでに進行中で、ポストフレーム コールバックの実行がまだ開始されていない場合、登録されたコールバックは現在のフレームの終わりに実行されます。 それ以外の場合、登録されたコールバックは次のフレームの後に実行されます (実行される可能性がある場合はいつでも)。

コールバックは追加された順序で実行されます。

ポストフレーム コールバックは登録解除できません。 これらは 1 回だけ呼び出されます。

以下も参照してください。

scheduleFrameCallback: 次のフレームの開始のためのコールバックを登録します。

void addPostFrameCallback(FrameCallback callback) {
  _postFrameCallbacks.add(callback);
}

summary

initStateの中で、スナックバーを表示するコードを実行したい。しかしそのまま関数を実行しただけでは、エラーが発生する!

🤪よくない例

通常は、initStateの中でcontextを参照することができないため、エラーが発生する。

import 'package:flutter/material.dart';

class OnCallBackExample extends StatefulWidget {
  const OnCallBackExample({Key? key}) : super(key: key);

  
  State<OnCallBackExample> createState() => _OnCallBackExampleState();
}

class _OnCallBackExampleState extends State<OnCallBackExample> {
  // スナックバーを出すだけのメソッド
  void snackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('initStateでcontextを参照'),
      ),
    );
  }

  
  void initState() {
    super.initState();
    // このコードだとcontextを参照することができない!
    snackBar();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('addPostFrameCallback'),
      ),
    );
  }
}

エラーが出た時のスクリーンショット

😄解決策

addPostFrameCallbackを使うことで、initStateの後にコールバック関数を実行することができる。

ライフサイクルの仕組みとしては、initStateの後にコールバック関数を実行するということになる。

import 'package:flutter/material.dart';

class OnCallBackExample extends StatefulWidget {
  const OnCallBackExample({Key? key}) : super(key: key);

  
  State<OnCallBackExample> createState() => _OnCallBackExampleState();
}

class _OnCallBackExampleState extends State<OnCallBackExample> {
  // スナックバーを出すだけのメソッド
  void snackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('initStateでcontextを参照'),
      ),
    );
  }

  
  void initState() {
    super.initState();
    // このコードだとcontextを参照することができない!
    // snackBar();
    // このコードだとcontextを参照することができる!
    WidgetsBinding.instance.addPostFrameCallback((_) {
      snackBar();
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('addPostFrameCallback'),
      ),
    );
  }
}

ビルドした時にエラーが発生せず、スナックバーがページが呼ばれた時に表示される。

thoughts

最近仕事で使われているのをよく見かけて、どんなコードなんだろうなと調べていたのですが、単純にinitStateの中では、contextを参照できないそうでaddPostFrameCallback methodを使ってページが呼ばれたときに実行する必要があるということでした。

参考になった情報
https://tech.pepabo.com/2020/05/27/flutter-hands-on/

Jboy王国メディア

Discussion