【问题标题】:Turning a FutureProvider into a Provider将 FutureProvider 变成 Provider
【发布时间】:2021-02-04 10:10:43
【问题描述】:

我使用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 很陌生,我不确定是否以及如何在另一个提供程序中创建一个提供程序。

【问题讨论】:

  • 你已经完成了——比如,你没有在 FutureProvider 中使用 async/await,所以只需将其更改为 Provider。
  • 抱歉,问题可能不清楚,但FirestoreDatabase.create(user: user) 函数是异步的,所以我不能只将FutureProvider 更改为Provider。
  • 我已经编辑了这个问题。我希望现在更清楚我想要实现的目标。

标签: flutter riverpod


【解决方案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")),
      ),
    );
  }
}

【讨论】:

    猜你喜欢
    • 2019-12-12
    • 2023-01-02
    • 2020-05-11
    • 2021-11-15
    • 1970-01-01
    • 2022-08-14
    • 2021-11-22
    • 2020-11-11
    • 2021-12-24
    相关资源
    最近更新 更多