簡體   English   中英

如何通過 Riverpod 的 FutureProvider 初始化 Firebase

[英]How to initialize Firebase via Riverpod's FutureProvider

在 Flutter 應用程序中使用 Firebase 的第一步是執行初始化。

我已經嘗試在 main() 中這樣做並且它有效

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

I've utilized Riverpod for state management - with Provider for firebase instance and access to the class with connection methods (Signin, Signout...) and StreamProvider for user state. 這再次工作正常 - 識別用戶何時登錄或退出 - 重建小部件並重定向到正確的屏幕......

現在我還想將上面粘貼的代碼從 main() 移動到提供程序定義中,並根據 firebase 初始化的狀態顯示正確的屏幕。

我已經看到官方 Firebase 示例建議為此使用 FutureBuilder - 但是,由於我使用過 Riverpod - 我的想法是使用FutureProvider來初始化 firebase。 但是,無論我嘗試什么,該應用程序都會因一些 null 異常而崩潰。

如果有人可以通過 FutureProvider 分享他們的firebase.initializeApp()示例,那就太好了。

我這樣做:(如果需要,可以通過 singleton 完成)

// services_initialization.dart
class ServiceInit{
  ServiceInit(ProviderContainer container) {
    _container = container;
  }

  // The container is needed to access the ref and load other providers, if required
  late final ProviderContainer _container;

  Future<void> init() async {
    await _initFirebase();
    // initialization of other services, example:
    await _container.read(somethingFutureProvider.future);
  }

  Future<void> _initFirebase() async {
    await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    );
  }
}

主文件如下所示:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final _container = ProviderContainer();
  await ServiceInit(_container).init();

  runApp(UncontrolledProviderScope(
      container: _container,
      child: WeatherMain(),
    ),
}

我已經找到了解決方案,因此將其粘貼在下面。 非常感謝 2002Bishwajeet,他在 GitHub 上發布了涵蓋此主題的 Firebase 和Riverpod身份驗證示例

這個想法是像這樣創建 FutureProvider :

final firebaseInitProvider = FutureProvider<FirebaseApp>((ref) async 
{ 
  return await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
});

在 main() 中只保留WidgetsFlutterBinding.ensureInitialized()像這樣:

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

然后觀察提供者和 use.when() 以顯示正確的屏幕 - 基本上只有在 Firebase.initializeApp() 完成初始化過程后才移動到 AuthenticationWrapper 小部件。

像這樣:

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _initializeFirebase = ref.watch(firebaseInitProvider);

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Firebase Authentication App',
      theme: CommonTheme().mainThemeData,
      home: _initializeFirebase.when(
        data: (data) => const AuthenticationWrapper(),
        loading: () => const ProgressScreen(),
        error: (error, stackTrace) => ErrorScreen(error.toString()),
      ),
    );
  }
}

最后,AuthenticationWrapper 正在處理登錄或主屏幕的顯示 - 取決於用戶的狀態(是否已在 Firebase Auth 登錄)。

像這樣:

class AuthenticationWrapper extends ConsumerWidget {
  const AuthenticationWrapper({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _authState = ref.watch(authStateProvider);

    return _authState.when(
      data: (value) {
        if (value != null) {
          return HomeScreen();
        } else {
          return LoginScreen();
        }
      },
      error: ((error, stackTrace) => ErrorScreen(error.toString())), //TO-DO set user oriented error messages
      loading: (() => ProgressScreen()),
    );
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM