Heck Codes
Heck Codes

Reputation: 161

Flutter: Weird listview/stream builder behavior

I have a home_page.dart file whose body has a StreamBuilder it recieves the stream from my getChats() function. In the StreamBuilder's builder function I sort the all the documents after storing them in a list named docsList based on the lastMessageTime field so that the document with the latest message is at the top (first).

As the ListView is using the docsList for building the cards it is expected that the document which has the most resent message should be displayed first. Which only happens when the list is build for the first time. After that if I send a new message to the chat which is not at the top this happens:

Initially:

When I send a message which the text 'test' to the chat "Heah Roger" this is how the list gets updated:

As it can be seen the Time on the right and the subtext changes for the first tile but the image and name didn't (same for second tile). Even though the documents are updated in the docsList and are sorted in the desired manner (I printed it to check it). Somehow the photo and the name alone are not being updated in the UI alone.

Note: The correct fields are updated in the firestore. Also if I restart the app after killing it. It shows the desired result:

Stream<QuerySnapshot<Map<String, dynamic>>> getChats(User currentUser) {
  return FirebaseFirestore.instance
      .collection('chats')
      .where('users', arrayContains: currentUser.id)
      .snapshots();
}
body: StreamBuilder(
    stream: RepositoryProvider.of<FirestoreRepository>(context).getChats(BlocProvider.of<AuthenticationBloc>(context).state.user),
    builder: (context, AsyncSnapshot<dynamic> snapshot) {

      if (snapshot.hasData && snapshot.data.docs.length > 0) {

        List docsList = snapshot.data.docs;
        docsList.sort((a, b) => b.data()['lastMessageTime'].compareTo(a.data()['lastMessageTime']));

        return ListView.builder(
          itemCount: docsList.length,
          itemBuilder: (context, index) {
            return SingleChatCard(chatRoom: ChatRoomModel.fromMap(docsList[index].data()));
          },
        );

      } else {
          return ...
      }
    },
 ),

Can anyone help me figure out the underlying problem that is causing this weird behavior?

Upvotes: 1

Views: 552

Answers (1)

Aditya
Aditya

Reputation: 330

Looks like an key issue to me, When you're using your custom Widget to render in a listview, with some complicate data flow, Flutter react to these changes one level at a time: You can refer: https://www.youtube.com/watch?v=kn0EOS-ZiIc

In your example, you can do something like this:

 return SingleChatCard(
      key: ValueKey(index), 
      chatRoom: ChatRoomModel.fromMap(docsList[index].data()));
    },

Upvotes: 1

Related Questions