在 Firebase.initializeApp() 完成之前依赖于 firebase 的根提供者获取值

Provider at root dependent on firebase fetches value before Firebase.initializeApp() completes

因此,我正在构建一个带有 MultiProvider 的应用程序,该应用程序位于 MaterialApp() 之上的应用程序的根目录中(以便该值在我导航到的所有 sub-widgets 和后续页面中都可用还有)。

对于我的主要功能:

void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
   }

MyApp class 是:

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  DarkThemeProvider themeChangeProvider = DarkThemeProvider();
  final Future<FirebaseApp> _firebaseApp = Firebase.initializeApp();

  void getCurrentAppTheme() async {
    themeChangeProvider.darkTheme =
    await themeChangeProvider.darkThemePreference.getTheme();
  }

  @override
  void initState() {
    super.initState();
    getCurrentAppTheme();
  }

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => themeChangeProvider,
        ),
        ChangeNotifierProvider(
          create: (_) => VideoPlayService.instance(),
        ),
        ChangeNotifierProvider(
          create: (_) => FirestoreAPI.instance(),
        ),
        ChangeNotifierProvider(
          create: (_) => AuthUtil.instance(),
        ),
        ChangeNotifierProvider(
          create: (_) => PageSwitcher.instance(),
        ),
      ],
      child: Consumer5(
        builder: (
          ctx,
          DarkThemeProvider darkThemeProvider,
          VideoPlayService videoPlayService,
          FirestoreAPI firestoreAPI,
          AuthUtil user,
          PageSwitcher switcher,
          child,
        ) {
          return MaterialApp(
            debugShowCheckedModeBanner: false,
            themeMode: Provider.of<DarkThemeProvider>(ctx).getCurrentTheme,
            theme: DarkThemeProvider.customLightTheme,
            darkTheme: DarkThemeProvider.customDarkTheme,
            home: FutureBuilder(
              future: _firebaseApp,
              builder: (cx, snapshot) {
                if (snapshot.hasError) {
                  return const Center(
                    child: Text('Could not connect to firebase'),
                  );
                } else if (snapshot.connectionState == ConnectionState.done) {
                  return const Wrapper();
                } else {
                  return const SplashScreen();
                }
              },
            ),
          );
        },
      ),
    );
  }
}

我已经使用 future builder 通过 Firebase 初始化应用程序,但问题是提供者 AuthUtil 和 FirestoreAPI 都依赖于 firebase,现在如果我要删除它们并将它们添加为 child到 Future 构建器(在包装器之上)我将失去对整个应用程序中提供者的访问权限(因为提供者将不再位于根目录,它仅适用于第一个 child 并且每当我'我将导航到另一个页面,它将不可用。

在我编写的给定代码中,firebase 未初始化,但首先创建了 Provider 的实例,因此引发了 firebase 未初始化的异常,我还需要能够在 Firebase 初始化时显示 SplashScreen初始化时,我试图全神贯注于未来的提供者,但我不确定它们是如何工作的,甚至不确定它们是否与我的案例相关。

总而言之,我想先初始化 firebase,然后创建 AuthUtil 和 FirestoreAPI 的提供程序 class 同时保持在 firebase 初始化失败时显示启动画面或错误屏幕的方案,并将提供程序保持在根目录(为了记录,我确实尝试在根目录下创建一个 FutureBuilder,但它没有意义,我不得不为快照的情况调用多个 MaterialApp,这简直是无稽之谈)。

如果有人能尽快帮我解决这个问题...?这将是一个很好的节省。

我通常在我的主要方法中调用 initializeApp

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

虽然 initializeApp 调用是异步的,但它实际上只是对底层原生 SDK 的同步调用。所以我们在谈论 在这里等待 nano-seconds,而不是 FutureBuilder 有意义的数十到数百毫秒。