简体   繁体   中英

Flutter: StreamBuilder with Firebase

I have a ListView of objects from Firebase in which I would like to have it refresh using a StreamBuilder when the data changes.

I can load up my list fine & when data changes my list does refresh.

The issue I am having is instead of the ListTile that has the change just updating, I see that tile being duplicated so I see the new change & the old change.

Here's my setup:

final ref = FirebaseDatabase.instance.reference();
late DatabaseReference itemRef;
late FirebaseDatabase database = FirebaseDatabase();
late StreamSubscription _objectInfoStreamSub; // Not sure if needed?
late List<CustomObject> data = [];

@override
  void initState() {
    super.initState();

    final keys = Global.kData.keys;

    for (final key in keys) {
      // Initialize this...
      itemRef = database.reference().child('ABC').child(key.toString());
    }

    // Load the data...
    _setListeners();
}

// Here is where I load my data initially...
Future<void> _setListeners() async {
    // Clear out our data before we reload...
    data.clear();

    final keys = Global.kData.keys;

    for (final key in keys) {
      _objectInfoStreamSub =
          ref.child("ABC").child(key.toString()).onValue.listen(
        (event) {
          setState(() {
            // Mapped the data...
            final firebaseData = Map<String, dynamic>.from(event.snapshot.value);

            // Create the Room...
            final room = CustomObject.fromJson(firebaseData);

            // Check if blocked...
            // Logic to see if user is blocked
            
            // check if isArchived
            // Logic to see if room is archvied

            if (!isBlocked && !isArchived) {
              if (!data.contains(room)) {
                data.add(room);
              }
            }

            // Sort by date
            // Logic to sort so the most recent is at top
          });
        },
      );
    }
}

// Here is my updated StreamBuilder...
SliverToBoxAdapter(
  child: StreamBuilder<dynamic>(
    stream: itemRef.child('ABC').onValue,
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return Center(
          child: CircularProgressIndicator(),
        );
      }
      if (snapshot.hasData &&
                        snapshot.connectionState == ConnectionState.active) {
        return ListView.builder(
          physics: NeverScrollableScrollPhysics(),
          shrinkWrap: true,
          itemCount: data.length,
          itemBuilder: (BuildContext context, int index) {
            return ChatRoom(
              data: data[index],
            );
          },
        );
      } else {
        return Container();
      }
    },
  ),
),

Not sure if this causes your problem, but try wrapping the ListView.builder() with StreamBuilder instead of only it's items. Because in your current state of code, if you would add another item and your data.length would change, the ListView.builder() wouldn't get rebuilt and it wouldn't build new data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM