Albrino Fernando
Albrino Fernando

Reputation: 153

How to call a function once StreamBuilder fetches new data?

I'm currently working on a chat app and I want to scroll down to the latest message whenever a new message is posted. I decided to use a StreamBuilder as I'm using Cloud Firestore for data management. The problem is I'm not sure how to call my scrolling code whenever I get updated data from the StreamBuilder.

My current code:

StreamBuilder(
    stream: Firestore.instance.collection('chat').orderBy('sendTime').snapshots(),
    builder: (ctx, chatSnapshot) {
      if (chatSnapshot.connectionState == ConnectionState.waiting) {
        return Center(
          child: CircularProgressIndicator(),
        );
      }

      // Commented due to no scrollable widgets found yet
      // _scrollController.animateTo(
      //   _scrollController.position.maxScrollExtent,
      //   duration: const Duration(milliseconds: 300),
      //   curve: Curves.easeOut,
      // );
      
      final chatDocs = chatSnapshot.data.documents;
      return ListView.builder(
        controller: _scrollController,
        itemCount: chatDocs.length,
        itemBuilder: (ctx, index) => MessageBubble(
            message: chatDocs[index]['text'],
            isUser: chatDocs[index]['userId'] == futureSnapshot.data.uid,
            key: ValueKey(chatDocs[index].documentID),
            userName: chatDocs[index]['userName'],
            imageUrl: chatDocs[index]['userImage']
          )
        );
      }
    )

Upvotes: 0

Views: 994

Answers (2)

Randal Schwartz
Randal Schwartz

Reputation: 44066

I'd use a RiverPod StreamProvider, and then subscribe to that provider in any place that needs to refresh on new Stream data.

Upvotes: 1

Maximilian V
Maximilian V

Reputation: 61

I think you should move the interaction with the scrollController outside the widget.

 var stream = Firestore.instance.collection('chat').orderBy('sendTime').snapshots();

 var subscr = stream.listen((snapshot) {
    _scrollController.animateTo(0.0, 
         curve: Curves.easeOut, 
         duration: Duration(milliseconds: 300)
    );
 });

Upvotes: 1

Related Questions