【Flutter×Firebase】Firebase.initializeAppが2回行われている
解決したいこと
FlutterとFirebaseでTwitterのクローンアプリを作っています。
Flutter runするたびに下記のようにFirebase.initializeAppが複数回行われてしまい、
エミュレーター画面が真っ白のまま先に進みません。
全テキスト検索をしてもmain.dart以外では呼び出されておらず、どうしたらいいか途方に暮れています。
おそらく使用しているパッケージかプラグインが別にFirebase.initializeAppを呼び出しているのではないかと思うのですが、特定ができない状況です。
発生している問題・エラー
Xcode build done. 18.4s
[VERBOSE-2:FlutterDarwinContextMetalImpeller.mm(37)] Using the Impeller rendering backend.
flutter: Firebase initializing...
flutter: Firebase initialization failed
flutter: Error: [core/duplicate-app] A Firebase App named "[DEFAULT]" already exists
flutter: StackTrace: #0 MethodChannelFirebase.initializeApp (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:134:11)
<asynchronous suspension>
#1 Firebase.initializeApp (package:firebase_core/src/firebase.dart:43:31)
<asynchronous suspension>
#2 main.<anonymous closure> (package:udemy_flutter_sns/main.dart:41:9)
<asynchronous suspension>
#3 main (package:udemy_flutter_sns/main.dart:33:3)
<asynchronous suspension>
Syncing files to device iPhone 15 Pro Max...
該当するソースコード
main.dart
//dart
import 'dart:async';
// flutter
import 'package:flutter/material.dart';
// packages
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:udemy_flutter_sns/constants/others.dart';
// models
import 'package:udemy_flutter_sns/models/main_model.dart';
import 'package:udemy_flutter_sns/models/mute_users_model.dart';
import 'package:udemy_flutter_sns/models/sns_bottom_navigation_bar_model.dart';
import 'package:udemy_flutter_sns/models/themes_model.dart';
// options
import 'firebase_options.dart';
// constants
import 'package:udemy_flutter_sns/constants/strings.dart';
import 'package:udemy_flutter_sns/constants/themes.dart';
// components
import 'package:udemy_flutter_sns/views/main/articles_screen.dart';
import 'package:udemy_flutter_sns/views/auth/verify_email_page.dart';
import 'package:udemy_flutter_sns/details/sns_bottom_navigation_bar.dart';
import 'package:udemy_flutter_sns/views/login_page.dart';
import 'package:udemy_flutter_sns/views/main/home_screen.dart';
import 'package:udemy_flutter_sns/views/main/search_page.dart';
import 'package:udemy_flutter_sns/views/main/profile_screen.dart'; // CupertinoWidgetsのためにimport追加
Future<void> main() async {
await runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load();
// Firebaseがまだ初期化されていない場合のみ、初期化を行う
if (Firebase.apps.isEmpty) {
try {
print("Firebase initializing..."); // ← この行を追加
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform);
print("Firebase initialized successfully."); // ← この行を追加
} catch (e, stackTrace) {
print('Firebase initialization failed');
print('Error: $e');
print('StackTrace: $stackTrace');
return;
}
}
runApp(const ProviderScope(child: MyApp()));
}, (error, stackTrace) {
if (Firebase.apps.isNotEmpty) {
FirebaseCrashlytics.instance.recordError(error, stackTrace);
} else {
print('Error occurred, but Firebase is not initialized');
print('Error: $error');
print('StackTrace: $stackTrace');
}
});
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
// FirebaseCrashlyticsインスタンスをここで設定します。
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
final User? onceUser = FirebaseAuth.instance.currentUser;
final ThemeModel themeModel = ref.watch(themeProvider);
// FutureBuilderは必要ないため、直接MaterialAppを返します。
return MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
debugShowCheckedModeBanner: false,
title: appTitle,
theme: themeModel.isDarkTheme
? darkThemeData(context: context)
: lightThemeData(context: context),
home: onceUser == null
? const LoginPage()
: onceUser.emailVerified
? MyHomePage(
themeModel: themeModel,
)
: const VerifyEmailPage(),
);
}
}
class SomethingWentWrong extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Something went wrong!'),
),
);
}
}
class Loading extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({Key? key, required this.themeModel}) : super(key: key);
final ThemeModel themeModel;
@override
Widget build(BuildContext context, WidgetRef ref) {
// MainModelが起動し、init()が実行されます
final MainModel mainModel = ref.watch(mainProvider);
final SNSBottomNavigationBarModel snsBottomNavigationBarModel =
ref.watch(snsBottomNavigationBarProvider);
return Scaffold(
body: mainModel.isLoading
? Center(
child: Text(returnL10n(context: context)!.loading),
)
: PageView(
controller: snsBottomNavigationBarModel.pageController,
onPageChanged: (index) =>
snsBottomNavigationBarModel.onPageChanged(index: index),
// childrenの個数はElementsの数
children: [
// 注意:ページじゃないのでScaffold
HomeScreen(
mainModel: mainModel,
themeModel: themeModel,
muteUsersModel: MuteUsersModel(),
),
SearchPage(
mainModel: mainModel,
),
const ArticlesScreen(),
ProfileScreen(
mainModel: mainModel,
),
],
),
bottomNavigationBar: SNSBottomNavigationBar(
snsBottomNavigationBarModel: snsBottomNavigationBarModel),
);
}
}
自分で試したこと
エラーハンドリング(print~)を細かくつけて、initializeAppが複数回呼び出されているところまで特定した。
他の.dartで呼び出されていないか確認して、コメントアウトされているところまで削除した。
GitHubコード
https://github.com/terisuke/FlutterSNS/tree/develop
0