将 FutureProvider 转变为提供者

时间:2021-02-04 10:10:43

标签: flutter riverpod

我使用 FirebaseAuth 进行身份验证,并定义了以下提供程序:

final _authStateChangesProvider = StreamProvider<User>(
    (ref) => ref.watch(authServiceProvider).authStateChanges);

数据库依赖于用户,所以只有在用户登录后我才能创建它。问题是数据库创建是异步的,所以它的提供者必须是 FutureProvider。

final databaseFutureProvider = FutureProvider<Database>((ref) {
  final authStateChange = ref.watch(_authStateChangesProvider);
  final user = authStateChange.data?.value;
  if (user != null) {
    return FirestoreDatabase.create(user: user);
  }
  throw UnsupportedError("The database cannot be accessed before the sign-in");
});

这会使整个应用的代码更加繁琐。我想让 databaseFutureProvider 成为一个简单的 Provider 以使应用程序的代码更简洁。怎么可能做到?

编辑

最好将数据库创建作为身份验证过程的一部分,这样 authStateChangesProvider 只会在数据库创建后触发。类似于以下内容:

final authStateChangesProvider = FutureProvider<User>((ref) {
  final authStateChanged = ref.watch(_authStateChangesProvider);
  final user = authStateChanged.data?.value;
  if (user != null) {
    // await the creation of the database provider
  }
  return user;
});

这样,只有 authStateChangesProvider 将成为 FutureProvider。但是我对 Riverpod 还很陌生,我不确定是否以及如何在另一个提供程序中创建提供程序。

1 个答案:

答案 0 :(得分:1)

我想出了一个可能不是最好的解决方案,但我会把它张贴在这里,以便其他人可以从中受益,或者希望可以改进它。

我创建了一个新的 ScopedProvider

final databaseProvider =
    ScopedProvider<Database>((ref) => throw UnimplementedError());

然后我创建了一个新的小部件,它将放在需要同步访问数据库的小部件树的顶部。此小部件将在创建数据库时仅显示加载视图,然后覆盖 databseProvider

class DatabaseWidgetBuilder extends ConsumerWidget {
  final Widget Function(Database) childBuilder;

  DatabaseWidgetBuilder(
      {Key key, @required Widget Function(Database) this.childBuilder})
      : super(key: key);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final databaseAsyncValue = watch(databaseFutureProvider);
    return databaseAsyncValue.when(
      data: (database) => ProviderScope(
        overrides: [databaseProvider.overrideAs((watch) => database)],
        child: childBuilder(database),
      ),
      loading: () => Scaffold(
        body: Center(child: CircularProgressIndicator()),
      ),
      error: (_, __) => Scaffold(
        body: Center(child: Text("Database Error")),
      ),
    );
  }
}
相关问题