logo
当前页

在聊天页面中渲染对话消息


功能简介

本文介绍了如何使用 ZIM SDK 在基本的聊天页面中渲染消息。

前提条件

已在项目中集成了 ZIM SDK 并实现了基本收发消息的功能,详情请参考 快速开始 - 实现基本收发消息

消息数据来源概述

页面上需要渲染的消息数据来源主要有以下几种:

  1. 历史对话消息: 首次进入聊天页面和查看历史消息时,需要查询历史对话消息并渲染到聊天界面。
  2. 实时收到的消息: 实时收到的聊天消息需要渲染到聊天界面。
  3. 本地发送的消息: 本地发送的聊天消息(包含发送中、发送成功、发送失败等状态)需要渲染到聊天界面。

获取消息数据渲染到聊天界面

以单聊会话为例,跳转到聊天页面时,需要保存对应单聊的 conversationID(对方的 userID)并维护一个用于保存当前会话的消息列表 myMessageList

在获取消息数据时建议实现 addMessage 工具方法用于合并历史消息、实时接收的消息和本地发送的消息。

public void addMessage(List<ZIMMessage> addList) {
    if (addList == null || addList.isEmpty()) return;

    List<ZIMMessage> mutableList = new ArrayList<>();
    if (myMessageList != null) {
        mutableList.addAll(myMessageList);
    }

    for (ZIMMessage newMsg : addList) {
        boolean replaced = false;
        for (int i = 0; i < mutableList.size(); i++) {
            ZIMMessage oldMsg = mutableList.get(i);
            if ((newMsg.getMessageID() != null && newMsg.getMessageID().equals(oldMsg.getMessageID())) ||
                (newMsg.getLocalMessageID() != null && newMsg.getLocalMessageID().equals(oldMsg.getLocalMessageID()))) {
                mutableList.set(i, newMsg);
                replaced = true;
                break;
            }
        }
        if (!replaced) {
            mutableList.add(newMsg);
        }
    }

    mutableList.sort(Comparator.comparingLong(ZIMMessage::getOrderKey));
    myMessageList = mutableList;
}
说明

每次调用消息相关的接口时(比如以下展示的接口),会得到一个消息列表 ZIMMessage[]。获得的消息列表需要进行合并数据的操作,从而得到一个无重复消息、有序的消息列表用于在消息页面进行渲染。消息排序规则为根据 ZIMMessage 中的 orderkey 属性进行排序(orderkey 越大表示当前消息越新);去重规则为根据消息的 localMessageID 判断消息对象是否为同一条消息,重复时新数据替换旧数据。

查询历史消息并渲染到聊天界面

调用 queryHistoryMessage 接口从新分页到旧分页(按时间顺序从最近的消息到更久之前的消息)进行查询,获取双方的历史消息并渲染到聊天界面。


ZIMMessageQueryConfig queryConfig = new ZIMMessageQueryConfig();
queryConfig.count = 20;
queryConfig.nextMessage = null; // 首次查询时为空,需要更多历史消息时传入最早消息

zim.queryHistoryMessage(
        myConversationID,
        ZIMConversationType.PEER,
        queryConfig,
        (conversationID, conversationType, messageList, errorInfo) -> {
            addMessage(messageList);
            // 更新 UI
        });

获取实时接收的消息并渲染到聊天界面

监听 onPeerMessageReceived 接口获取实时接收的消息,并渲染到聊天界面。

public void onPeerMessageReceived(ZIM zim, List<ZIMMessage> messageList, 
                                  ZIMMessageReceivedInfo info, String fromUserID) {
    // 只处理当前会话的消息
    if (!fromUserID.equals(myConversationID)) {
        return; // 非当前会话的消息忽略
    }

    // 合并消息到消息列表
    addMessage(messageList);

    // 更新 UI,比如刷新 RecyclerView
    runOnUiThread(() -> {
        myAdapter.notifyDataSetChanged();
        if (!myMessageList.isEmpty()) {
            recyclerView.scrollToPosition(myMessageList.size() - 1);
        }
    });
}

将本地发送的消息渲染到聊天界面

监听 onMessageSentStatusChanged ,获取本地发送消息的发送状态的变化(发送中、发送成功、发送失败),渲染本地发送的消息及其发送状态到聊天界面。


@Override
public void onMessageSentStatusChanged(List<ZIMMessageSentStatusChangeInfo> messageSentStatusChangeInfoList) {
    for (ZIMMessageSentStatusChangeInfo info : messageSentStatusChangeInfoList) {
        if (!info.getMessage().getConversationID().equals(myConversationID)) {
            continue;
        }
        addMessage(Collections.singletonList(info.getMessage()));
    }
    // 更新 UI
    runOnUiThread(() -> {
        myAdapter.notifyDataSetChanged();
        if (!myMessageList.isEmpty()) {
            recyclerView.scrollToPosition(myMessageList.size() - 1);
        }
    });
}

通过以上方式,即可实现在聊天页面中渲染历史消息、实时接收的消息和本地发送的消息(包含发送状态)。

Previous

噪声控制(ANS)

Next

订阅用户在线状态

当前页

返回到顶部