Home > Software design >  How to dispose of StreamBuilder value on sign out?
How to dispose of StreamBuilder value on sign out?

Time:10-05

I've been trying to retrieve user profiles to each user's account on sign in. Each user's information is stored in a doc with their respective uid's.

When a user registers and logs in, the data associated with the user displays correctly. However, when I create a second account and log in, the data associated with the second user displays for user 2 and user 1.

How do I dispose of the values in Streambuilder so each signed in user can see their profiles uniquely?

My code is below with a screenshot of my database

firestore db

FirebaseAuth _auth = FirebaseAuth.instance;
final uid = _auth.currentUser!.uid;
  final Stream<DocumentSnapshot<Map<String, dynamic>>> db = FirebaseFirestore
      .instance
      .collection('users')
      .doc(uid)
      .collection('Profile')
      .doc('Personal details')
      .snapshots();



                     Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text('First name'),
                        SizedBox(width: 40),
                        StreamBuilder<DocumentSnapshot>(
                          stream: db,
                          builder: (BuildContext context,
                              AsyncSnapshot<DocumentSnapshot> snapshot) {
                            if (snapshot.hasError)
                              return Text('Something went wrong');
                            if (snapshot.connectionState ==
                                ConnectionState.waiting)
                              return CircularProgressIndicator();

                            dynamic data = snapshot.data!.data();
                            return Text(data['First name']);
                            // return Text('First name', style: boldFont);
                          },
                        ),
                      ]),
                  Divider(color: Colors.black),
                  SizedBox(
                    height: 10,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text('Last name'),
                      SizedBox(width: 40),
                      StreamBuilder<DocumentSnapshot>(
                        stream: db,
                        builder: (BuildContext context,
                            AsyncSnapshot<DocumentSnapshot> snapshot) {
                          if (snapshot.hasError)
                            return Text('Something went wrong');
                          if (snapshot.connectionState ==
                              ConnectionState.waiting)
                            return CircularProgressIndicator();

                          dynamic data = snapshot.data!.data();
                          return Text(data['Last name'], style: boldFont);
                          // return Text('Last name', style: boldFont);
                        },
                      ),
                    ],
                  ),

My sign out code

onPressed: () async {
                        try {
                          await FirebaseAuth.instance.signOut();
                          errorMessage = '';
                        } on FirebaseAuthException catch (error) {
                          errorMessage = error.message!;
                        }
                        Navigator.of(context).pushReplacementNamed('/signIn');
                        setState(() {});
                      }

CodePudding user response:

I think will need StreamSubscription to subscription event from Stream. When user signin success you will listent data on this subscription. When user sign out, you will cancel current subscription. Example:

_streamSubscriptionMessage = FirebaseDatabase.instance
        .reference()
        .child('users')
        .child(sl.get<AuthCubit>().getUid().toString())
        .child('badgeMessage')
        .onValue
        .map<int>((event) {
      try {
        return event.snapshot.value as int;
      } catch (error) {
        return 0;
      }
    })

CodePudding user response:

You can use StatefulWidget, add a state variable to store current user, build using this, and apply setState whenever Firebase Authentication state changes:

User? _currentUser; // define in the widget's state class.

@override Widget build(BuildContext context) {
  if (_currentUser == null) {
    // you can add something here
    return;
  }
  final Stream<DocumentSnapshot<Map<String, dynamic>>> db = 
  FirebaseFirestore
      .instance
      .collection('users')
      .doc(_currentUser.uid),
      .collection('Profile')
      .doc('Personal details')
      .snapshots();
  // rest of your build
}

And add this to you Firebase Authentication listener or create if you don't have yet:

FirebaseAuth.instance.authStateChanges().listen((User? firebaseUser) {
  setState(() {
    _currentUser = firebaseUser;
  });
});

(It is a good idea to define this _currentUser at the main application level, and use ChangeNotifierProvider / Consumer / context.read etc.)

  • Related