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を安全に使用できます。