Kotlin如何为Room查询的聊天消息列表插入日期分隔项
Kotlin 聊天消息列表插入日期分隔符实现
最简方案(基于fold累加函数)
无需手动操作迭代器,代码逻辑清晰不易出错,首先确保你的消息列表已经按时间升序排序,再实现两个工具扩展(可根据你自己的ChatModel字段调整):
- 将时间字段转为仅包含年月日的字符串,用于判断是否为同一天:比如
Long.toDateOnlyString() - 将时间字段转为要展示的日期格式:比如
Long.toReadableTime()
核心代码如下:
.observe(viewLifecycleOwner) { messages -> val chatUiItems = messages.fold(mutableListOf<ChatUiModel>()) { acc, currentMsg -> val currentDate = currentMsg.time.toDateOnlyString() // 取已处理列表中最后一条聊天消息的日期 val lastChatDate = acc .filterIsInstance<ChatUiModel.ChatItem>() .lastOrNull() ?.message ?.time ?.toDateOnlyString() // 列表为空或者跨天的场景,先加日期分隔符 if (lastChatDate == null || lastChatDate != currentDate) { acc.add(ChatUiModel.DateSeparatorItem(currentMsg.time.toReadableTime())) } acc.add(ChatUiModel.ChatItem(currentMsg)) acc } chatAdapter.submitList(chatUiItems) }
原手写迭代器的问题
你之前的遍历逻辑存在隐藏bug:调用listIterator.previous()获取上一条元素后,迭代器游标会回退一位,没有复位的情况下后续遍历会重复读取同一条消息,容易出现死循环或者重复条目。
初始map写法不可行的原因
map是一对一转换操作,每个输入元素只能对应一个输出元素,无法满足「部分消息前额外插入分隔符」的需求;flatMap虽然支持一对多转换,但无法直接获取前一条消息的状态做日期对比,因此用fold做带状态的累加是最适配的方案。
内容的提问来源于stack exchange,提问作者Abhishek AN
相关产品推荐
相关产品推荐

