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
),
)