简体   繁体   English

如何通过 Riverpod 的 FutureProvider 初始化 Firebase

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

First step in using Firebase within Flutter app is to perform initialization.在 Flutter 应用程序中使用 Firebase 的第一步是执行初始化。

I've tried doing this within main() and it works我已经尝试在 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. 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. Again this works fine - recognizing when the user has signed in or signed out - rebuilding widgets and redirecting to proper screen...这再次工作正常 - 识别用户何时登录或退出 - 重建小部件并重定向到正确的屏幕......

Now I would like to also move the code pasted above from main() into a provider definition and have shown proper screen depending on the status of firebase initialization.现在我还想将上面粘贴的代码从 main() 移动到提供程序定义中,并根据 firebase 初始化的状态显示正确的屏幕。

I've seen official Firebase example suggesting to use FutureBuilder for this - however, since I've used Riverpod - my idea was to use FutureProvider for initializing firebase.我已经看到官方 Firebase 示例建议为此使用 FutureBuilder - 但是,由于我使用过 Riverpod - 我的想法是使用FutureProvider来初始化 firebase。 However, whatever I try the app keeps crashing with some null exceptions.但是,无论我尝试什么,该应用程序都会因一些 null 异常而崩溃。

If anybody can share their example of firebase.initializeApp() via FutureProvider it would be great.如果有人可以通过 FutureProvider 分享他们的firebase.initializeApp()示例,那就太好了。

I do it like this: (Can be done via singleton if needed)我这样做:(如果需要,可以通过 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,
    );
  }
}

The main file looks like this:主文件如下所示:

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

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

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

I've found a solution for this so pasting it bellow.我已经找到了解决方案,因此将其粘贴在下面。 Big thanks to 2002Bishwajeet who posted a Firebase & Riverpod authentication example covering this topic as well at GitHub非常感谢 2002Bishwajeet,他在 GitHub 上发布了涵盖此主题的 Firebase 和Riverpod身份验证示例

The idea is to create FutureProvider like this:这个想法是像这样创建 FutureProvider :

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

In the main() keep just WidgetsFlutterBinding.ensureInitialized() Like this:在 main() 中只保留WidgetsFlutterBinding.ensureInitialized()像这样:

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

Then watch the provider and use.when() to show the correct screen - basically to move to AuthenticationWrapper widget only once the Firebase.initializeApp() has completed the initialization process.然后观察提供者和 use.when() 以显示正确的屏幕 - 基本上只有在 Firebase.initializeApp() 完成初始化过程后才移动到 AuthenticationWrapper 小部件。

Like this:像这样:

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()),
      ),
    );
  }
}

And finally the AuthenticationWrapper is handling display of SignIn or Home screen - depending on the status of the user (already signed in at Firebase Auth or not).最后,AuthenticationWrapper 正在处理登录或主屏幕的显示 - 取决于用户的状态(是否已在 Firebase Auth 登录)。

Like this:像这样:

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