Flutter Provider: 提供2个流,其中一个依赖于另一个

12

我正在使用 provider 包。在组件树的根部,我有一个 MultiProvider:

Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        StreamProvider<FirebaseUser>.value(
            value: FirebaseConnection.getAuthenticationStream()),
        StreamProvider<User>.value(
            value: FirebaseConnection.getUserStream(uid: ???))
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        initialRoute: LoginScreen.id,
        onGenerateRoute: RouteGenerator.generateRoute,
      ),
    );
  }

第一个StreamProvider提供来自firebase_auth的已登录用户。 第二个StreamProvider应该为该用户提供其他信息(存储在用户集合中)。 问题是,要获取第二个流,我需要使用第一个流所提供的FirebaseUser的UID,但我不知道如何访问它。

嵌套StreamProviders没有起作用,因为在第二个流中,我只能访问构建方法的(错误)上下文(对于Provider.of(context))。


FirebaseConnection 是你自己创建的类吗?我在 Firebase 文档中找不到它。 - Abion47
是的,它是包含返回流的函数的类。 - Isaak
你预计从第一个流中会得到多少响应?你只是用它来处理第二个流吗? - Abion47
检查用户是否已登录并获取其UID以便提供给第二个流是我需要第一个流的唯一原因(当没有用户登录时,第一个流返回null)。如果我可以让第二个流在没有用户登录时也返回null,那么我就不需要第一个流了。 - Isaak
也许可以不将第一个流提供给自己的提供程序,而是单独创建流,监听第一个事件,并使用事件数据创建第二个流。将所有这些放入异步方法中,以异步方式返回流,并从FutureBuilder中调用它。一旦未来完成并返回流,请将其传递给提供程序。 - Abion47
谢谢。你的建议帮助我想出了解决方案。 - Isaak
1个回答

3
解决方案是将第二个流(loggedInUserStream)保存在状态中,并在第一个流(authenticationStream)发出新值时更改它(通过监听它),如下面的代码所示:
class _FloatState extends State<Float> {
  StreamSubscription<FirebaseUser> authenticationStreamSubscription;
  Stream<User> loggedInUserStream;

  StreamSubscription<FirebaseUser> setLoggedInUserStream() {
    authenticationStreamSubscription =
        FirebaseConnection.getAuthenticationStream().listen((firebaseUser) {
      loggedInUserStream =
          FirebaseConnection.getUserStream(uid: firebaseUser?.uid);
    });
  }

  @override
  void initState() {
    super.initState();
    authenticationStreamSubscription = setLoggedInUserStream();
  }

  @override
  void dispose() {
    super.dispose();
    authenticationStreamSubscription.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return StreamProvider<User>.value(
      value: loggedInUserStream,
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        initialRoute: LoginScreen.id,
        onGenerateRoute: RouteGenerator.generateRoute,
      ),
    );
  }
}

我只需要第一个流(authenticationStream)来获取第二个流(loggedInUserStream),所以我没有将其提供给下面的小部件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接