Home > front end >  ListView.builder build new elements using Bloc?
ListView.builder build new elements using Bloc?

Time:12-20

I'm using GroupedListView (which is based on ListView.builder) to implement a chat.

I have a ChatBloc bloc that is responsible to handle new messages from the DataLayer. Whenever the state of the messages updates, I rebuild the whole ListView.

Here is my code:

child: BlocBuilder<ChatBloc, ChatState>(
  builder: (context, state) {
    final userId = context.read<AppBloc>().state.user.userId;
    return GroupedListView<Message, DateTime>(
    controller: scrollController,
    elements: state.messages,
    reverse: true,
    cacheExtent: 9999,
    order: GroupedListOrder.DESC,
    itemComparator: (element1, element2) =>
      element1.timestamp.compareTo(element2.timestamp),
    itemBuilder: (context, element) =>
      element.messageToWidget(userId, state.senders),
    groupBy: (element) => DateTime(
      element.timestamp.year,
      element.timestamp.month,
      element.timestamp.day,
    ),
    groupHeaderBuilder: (element) => Center(
    child: TitleMessage(
    text: dateFormat03.format(element.timestamp),
    ),
   ),
  );
 },
)

The problem is that I don't want to rebuild every message again, with every new message that is added to the list.

I want to build new messages only.

How do I do that using Bloc state management?

CodePudding user response:

You can listen to your blocStream in initState and use animated list instead of your current list so you can insert items in real time

It can be done by defining a global ket like this:

final GlobalKey<AnimatedListState> messagesKey = GlobalKey<AnimatedListState>();

and then inserting the value like:

messagesList.add(NEW_MESSAGE);
messagesKey.currentState?.insertItem(messagesList.length - 1);

and if you want to remove an item with animations you can:

  messagesKey.currentState?.removeItem(
  index,
  (context, animation) => buildMessage(index, animation),
);

CodePudding user response:

Don't wrap your ListView with a bloc builder in that case, use BlocListener

BlocListener<BlocA, BlocAState>(
  listener: (context, state) {
    setState((){
       // Have a copy of messages in your widget and update it as you wish (implement getNewMessages)
       messages = getNewMessages(state.messages)
    })
  },
  child: ListView.builder(
     elements: messages
  ),
)
  • Related