- 開発技術
【Flutter】非同期の遅延初期化によるLateInitializationErrorについて
- Flutter
はじめに
【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc. 詳細はこちらから>
Flutterにおいて非同期処理で遅延初期化をする際に、LateInitializationErrorが発生することがあります。この記事では、非同期の遅延初期化によるLateInitializationError発生例とFutureBuilderを用いた解決策についてご紹介します。
遅延初期化(Late Initialization)とは
下記のように、late修飾子を付けて変数を宣言した場合、宣言時の初期化なしでnon-nullableな変数を宣言できます。この変数は、使用される前に初期化される必要があります。初期化前に変数がアクセスされた場合、LateInitializationErrorが発生します。
1 |
late String _text; |
非同期の遅延初期化によるLateInitializationError発生例
下記の例では、late修飾子とともに宣言された変数_textが非同期で初期化されています。その非同期処理が完了する前にbuild()が実行され、_textが初期化される前にアクセスされることにより、LateInitializationErrorが発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// 省略 class _MyHomePageState extends State<MyHomePage> { late String _text; @override void initState() { super.initState(); // 非同期処理 performAsyncTask(); } Future<void> performAsyncTask() async { await Future.delayed(const Duration(seconds: 3)); _text = '初期化されました'; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('initState内の非同期処理'), ), body: Center( child: Text(_text), ), ); } } |
解決策(FutureBuilderの使用)
上記のLateInitializationErrorの解決策として、FutureBuilderで非同期処理の完了を待つ方法があります。FutureBuilderを使用すると、非同期処理の実行状況に応じた処理を実装することができます。下記の例では、非同期処理の結果をFuture<void>型の_initializationFutureに保持し、FutureBuilderのfutureに設定しています。非同期処理完了前はローディングを表示し、非同期処理が完了してから_textにアクセスするようにしています。このように、FutureBuilderを使用して遅延初期化前の変数へのアクセスによるLateInitializationErrorを防ぐことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// 省略 class _MyHomePageState extends State<MyHomePage> { late final String _text; late final Future<void> _initializationFuture; @override void initState() { super.initState(); // 非同期処理の結果を保持する _initializationFuture = performAsyncTask(); } Future<void> performAsyncTask() async { await Future.delayed(const Duration(seconds: 3)); _text = '初期化されました'; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('initState内の非同期処理'), ), body: Center( child: FutureBuilder<void>( future: _initializationFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // 非同期処理の完了前 return const CircularProgressIndicator(); } else if (snapshot.hasError) { // 非同期処理のエラー時 return Text('Error: ${snapshot.error}'); } else { // 非同期処理完了時 return Text(_text); } }, ), ), ); } } |
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>