FlutterでFlutter runでは動くのにVScodeの実行ができない
状況
Firebase導入時にかなりこの問題にハマりました。
状況として、
・Flutter runでは問題なくビルドできる
・Android Studioでもビルドできる
・VSCodeからのデバックのみ白画面が出力され実行できない
・Firebase導入の直前まで動作していた
こんな感じです。
VSCodeのみ実行できないことからVSCodeとシミュレーターの問題だと思いかなり時間を費やしてしまいました、、
結論から言うとVSCodeに問題はなく、以下が原因でした。(疑ってごめんね、、)
結論:Firebase.initializeApp() が完了する前にウィジェットが構築されていたこと!
解決前のコードがこちらです。
main.dart
// ---省略---
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // 追加
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'naily',
),
home: userState() ? const FeedPage() : const LoginPage(),
);
}
}
このコードのざっくりとした流れは
- Firebase.initializeApp()でFirebase を初期化
- runApp() でアプリ本体を動かす
- userState(Firebaseを使用する関数)を実行
つまり、
Firebase.initializeApp() の非同期処理が完了する前に
userState()(Firebaseを使用する関数)が呼ばれ、null を返していたため、白画面が表示されてしまっていた
これでした。
この問題を解決するために以下を実行しました。
FutureBuilderでFirebaseの初期化が終わってから画面を表示
改善したコードが以下です。
main.dart
//---省略---
/// Firebaseの初期化を待ってからMyAppを表示
class AppInit extends StatelessWidget {
const AppInit({super.key});
Widget build(BuildContext context) {
return FutureBuilder(
future: Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
),
builder: (context, snapshot) {
// ローディング中
if (snapshot.connectionState == ConnectionState.waiting) {
return const MaterialApp(
home: Scaffold(
body: Center(child: CircularProgressIndicator()),
),
);
}
// エラー時
if (snapshot.hasError) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Text('🔥 Firebase初期化エラー: ${snapshot.error}'),
),
),
);
}
// 初期化完了
return const MyApp();
},
);
}
}
class MyApp extends StatelessWidget {
// ---省略---
ここでは3つの状態があります。
Firebaseの準備中 :ConnectionState.waiting ローディングのぐるぐる
初期化に成功 :ConnectionState.done MyApp() を表示する
初期化に失敗 :snapshot.hasError == true エラーメッセージ表示
これでFirebaseの初期化が終わってから画面を表示できるようになりました!
なぜFlutter runでは動いたのか
flutter run では Firebase の初期化がたまたま早く終わっていたため、UserState が正しく取得できていたようです。
逆に VSCode のデバッグは初期化がシビアで、runApp() までが早すぎて UserState が null だったため白画面が表示された。と言う流れでした。
まとめ
非同期初期化が必要な処理(Firebaseなど)は、必ず初期化完了を待ってから使うこと!
特に FirebaseAuth のように起動直後に使う場合は、FutureBuilder や async対応の初期化処理を正しく挟むようにします。
Discussion