フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

【flutter】late 変数とは

dart.dev

The late modifier has two use cases:

Declaring a non-nullable variable that’s initialized after its declaration. Lazily initializing a variable. Often Dart’s control flow analysis can detect when a non-nullable variable is set to a non-null value before it’s used, but sometimes analysis fails. Two common cases are >top-level variables and instance variables: Dart often can’t determine whether they’re set, so it doesn’t try.

If you’re sure that a variable is set before it’s used, but Dart disagrees, you can fix the error by marking the variable as late:

non-null な値を宣言するが、初期化はその時点では行わないようなケースで使う宣言方法。文字通り 後で(late) ということか。

Flutter 開発入門の p133 で登場したときも late AnimationController _animationController; のように後工程の initState() で初期化をしているため late が用いられていた。

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  late AnimationController _animationController;

  _forward() async {
    setState(() {
      _animationController.forward();
    });
  }

  _stop() async {
    setState(() {
      _animationController.stop();
    });
  }

  _reverse() async {
    setState(() {
      _animationController.reverse();
    });
  }

  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 3));
  }

...

じゃあコンストラクタで定義すればいいなじゃないかということでやってみましたが、これは vsync: this のところでエラーになります。

  final AnimationController _animationController;

  _MyHomePageState() :_animationController = AnimationController(vsync: this, duration: const Duration(seconds: 3));

調べると vsync は {required TickerProvider vsync} となっており、TickerProvider は _MyHomePageState に mixin されているため _MyHomePageState の初期化が終わらないと TickerProvider(として使える_MyHomePageState) が用意できないようです。

ChatGPT の回答をぺたり

AnimationControllerのようなクラスは、vsyncパラメータとしてTickerProviderのインスタンスを必要とします。StateクラスがTickerProviderStateMixinを実装している場合、そのStateオブジェクト自体がTickerProviderの役割を果たすことができます。

しかし、Stateオブジェクトのコンストラクタでは、Stateオブジェクト自体がまだ完全に初期化されていないため、this(つまりStateオブジェクト自体)をvsyncとして使用することはできません。これは、StateオブジェクトがFlutterフレームワークによって完全に構築される前に、thisを使用して何かを行うと、未定義の状態やエラーにつながる可能性があるためです。

したがって、AnimationControllerのようなオブジェクトは、StateオブジェクトのinitStateメソッド内で初期化するのが一般的です。initStateはStateオブジェクトが完全に初期化された後に呼び出されるため、この時点でthisを安全に使用できます。