Flutter Provider: Provide 2 streams with one dependent on the other

2,579

The solution is to save the second stream (loggedInUserStream) in the state and change it whenever the first stream (authenticationStream) emits a new value (by listening to it) like in the code below:

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

I only needed the first stream (authenticationStream) to get the second one (loggedInUserStream) so I didn't provide it to the widgets below.

Share:
2,579
Isaak
Author by

Isaak

Updated on December 16, 2022

Comments

  • Isaak
    Isaak over 1 year

    I'm using the provider package. In the root of the widget tree I have a 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,
          ),
        );
      }
    

    The first StreamProvider provides the logged in user from firebase_auth. The second StreamProvider is supposed to provide additional information to that user (stored in the users collection). The problem is that to get the second stream I need the uid of the FirebaseUser provided with the first stream but I don't know how to access it.

    Nesting the StreamProviders didn't work because in the second stream I can only access the (wrong) context of the build method (for Provider.of(context))