繁体   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