Flutter

最近更新时间:2023-07-18 11:54:11

我的收藏

功能描述

用户在登录 App 后,可以像微信或 QQ 那样展示最近会话列表,方便找到目标会话。会话列表如下图所示:

会话列表功能主要分为获取会话列表、处理会话列表更新。本文将为您介绍具体的实现细节。

获取会话列表

您可以调用 getConversationList(点击查看详情) 获取会话列表。该接口拉取的是本地缓存的会话,如果服务器会话有更新,SDK 内部会自动同步,然后在 V2TIMConversationListener 回调告知客户。
用户的会话以列表的形式返回,列表中存储的是 V2TIMConversation 对象。目前 IM SDK 对会话列表的排序规则为:
Flutter sdk 3.8.0及以后版本, 该接口获取的会话列表默认已经按照会话对象的 orderKey 做了排序。orderKey 值越大,代表该会话排序越靠前。orderKey 字段是整型数,当发送新消息、接收新消息、设置草稿或置顶会话时,会话被激活,orderKey 字段会增大。
Flutter sdk 3.8.0 以前版本,该接口获取的会话列表默认已经按照会话 lastMessage -> timestamp 做了排序。timestamp 越大,会话越靠前。
注意
在某些场景下,可能出现会话的 lastMessage 为空(例如清空会话消息)。如果您使用 3.8.0以前的 SDK,使用 lastMessage 排序时需要额外处理这种异常。我们建议您升级到 3.8.0 及以后的版本,使用 orderKey 字段排序。
您可以使用 getConversationList 实现一次性拉取或分页拉取。参考下文说明。

一次性拉取

一次性拉取适合会话数量比较少的情况(100 个以内)。此时可以将拉取的 count 设置为 INT_MAX(一般会话数量不会达到 INT_MAX 这么多)。
示例代码如下:
V2TimValueCallback<V2TimConversationResult> convList = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: '0',count: 100);

分页拉取

如果您的应用场景会产生较多的会话数,考虑到加载效率、网络省流,我们建议您采用分页拉取的方式。每次分页拉取的数量建议不超过 100 个。
分页拉取的步骤:
1. 首次调用 getConversationList 时,指定参数 nextSeq 为 0(表示从头开始拉取会话列表),指定 count 为 50(表示一次拉取 50 个会话对象)。
2. 首次拉取会话列表成功后,getConversationList 的回调结果 V2TIMConversationResult 中会包含 nextSeq(下次分页拉取的字段)、isFinished(会话拉取是否完成)。
如果 isFinished 为 true,表示所有会话已经拉取完成。
如果 isFinished 为 false,表示还有更多的会话可以拉取。此时并不意味着要立刻开始拉取 “下一页” 的会话列表。在常见的通信软件中,分页拉取通常由用户的滑动操作触发的,用户每上拉一次会话列表就触发一次分页拉取。
3. 当用户继续上拉会话列表时,如果还有更多的会话可以拉取,可以继续调用 getConversationList 接口,并传入新一轮的 nextSeqcount 参数(数值来自上一次拉取返回的 V2TIMConversationResult 对象)。
4. 重复执行 步骤 3 直至 isFinished 返回 true。
示例代码如下:
//获取会话列表
V2TimValueCallback<V2TimConversationResult> getConversationListRes =
await TencentImSDKPlugin.v2TIMManager
.getConversationManager()
.getConversationList(
count: 100, //分页拉取的个数,一次分页拉取不宜太多,会影响拉取的速度,建议每次拉取 100 个会话
nextSeq: "0"//分页拉取的游标,第一次默认取传 0,后续分页拉传上一次分页拉取成功回调里的 nextSeq
);
if (getConversationListRes.code == 0) {
//拉取成功
bool? isFinished = getConversationListRes.data?.isFinished;//是否拉取完
String? nextSeq = getConversationListRes.data?.nextSeq;//后续分页拉取的游标
List<V2TimConversation?>? conversationList =
getConversationListRes.data?.conversationList;//此次拉取到的消息列表
//如果没有拉取完,使用返回的nextSeq继续拉取直到isFinished为true
if (!isFinished!) {
V2TimValueCallback<V2TimConversationResult> nextConversationListRes =
await TencentImSDKPlugin.v2TIMManager
.getConversationManager()
.getConversationList(count: 100, nextSeq: nextSeq = "0");//使用返回的nextSeq继续拉取直到isFinished为true
}

getConversationListRes.data?.conversationList?.forEach((element) {
element?.conversationID;//会话唯一 ID,如果是单聊,组成方式为 c2c_userID;如果是群聊,组成方式为 group_groupID。
element?.draftText;//草稿信息
element?.draftTimestamp;//草稿编辑时间,草稿设置的时候自动生成。
element?.faceUrl;//会话展示头像,群聊头像:群头像;单聊头像:对方头像。
element?.groupAtInfoList;//群会话 @ 信息列表,通常用于展示 “有人@我” 或 “@所有人” 这两种提醒状态。
element?.groupID;//当前群聊 ID,如果会话类型为群聊,groupID 会存储当前群的群 ID,否则为 null。
element?.groupType;//当前群聊类型,如果会话类型为群聊,groupType 为当前群类型,否则为 null。
element?.isPinned;//会话是否置顶
element?.lastMessage;//会话最后一条消息
element?.orderkey;//会话排序字段
element?.recvOpt;//消息接收选项
element?.showName;//会话展示名称,群聊会话名称优先级:群名称 > 群 ID;单聊会话名称优先级:对方好友备注 > 对方昵称 > 对方的 userID。
element?.type;//会话类型,分为 C2C(单聊)和 Group(群聊)。
element?.unreadCount;//会话未读消息数,直播群(AVChatRoom)不支持未读计数,默认为 0。
element?.userID;//对方用户 ID,如果会话类型为单聊,userID 会存储对方的用户 ID,否则为 null。
});
}

会话列表更新

IM SDK 会在登录成功后、用户上线后、以及断线重连后,自动更新会话列表。 为了获取会话列表的更新,您需要操作如下几步:
1. 添加会话监听器。
2. 接收会话变更通知并处理。
3. 移除会话监听器。非必须,可按照业务逻辑按需调用。

添加会话监听器

您可以调用 addConversationListener(点击查看详情) 添加会话监听器。添加监听器后,您才能接收到会话变更事件。
示例代码如下:
TencentImSDKPlugin.v2TIMManager.getConversationManager().addConversationListener(listener: V2TimConversationListener(onConversationChanged: (conversationList) {

},
//其他 ));

会话新增变更通知

您可以在 V2TIMConversationListener(点击查看详情) 中的事件,获取会话列表变更的通知。
目前 IM SDK 支持的会话变更事件有:
事件
说明
建议
onSyncServerStart
同步服务器会话开始
SDK 会在登录成功或者断网重连后自动同步服务器会话,您可以监听这个事件做一些 UI 进度展示操作。
onSyncServerFinish
同步服务器会话完成
如果会话有变更,会通过 onNewConversation/onConversationChanged 回调告知。
onSyncServerFailed
同步服务器会话失败
您可以监听这个事件做一些 UI 异常展示操作。
onNewConversation
有会话新增
例如收到一个新同事发来的单聊消息、被拉入了一个新的群组中,此时可以重新对会话列表做排序。
onConversationChanged
有会话更新
例如未读计数发生变化、最后一条消息被更新等,此时可以重新对会话列表做排序。
onTotalUnreadMessageCountChanged
会话未读总数变更通知
详情请参考 会话未读数
说明
为保证会话列表顺序符合最后一条消息的排序原则,每次会话变更/新增后,您需要对数据源重新排序。
如果您使用 Flutter sdk 3.8.0 以前的版本,可以使用 lastMessage 排序,但是需要注意处理 lastMessage 为空(例如清空会话消息)的情况。
如果您使用 Flutter sdk 3.8.0 及以后的版本,使用 orderKey 字段排序。
我们强烈建议您升级到 Flutter sdk 3.8.0 及以后版本。
示例代码如下:
//设置群组监听器
V2TimGroupListener listener = V2TimGroupListener(onApplicationProcessed:
(String groupID, V2TimGroupMemberInfo opUser, bool isAgreeJoin,
String opReason) async {
//加群请求已经被群主或管理员处理了(只有申请人能够收到)
//groupID 群 ID
//opUser 处理人
//isAgreeJoin 是否同意加群
//opReason 处理原因
}, onGrantAdministrator: (String groupID, V2TimGroupMemberInfo opUser,
List<V2TimGroupMemberInfo> memberList) async {
//指定管理员身份
//groupID 群 ID
//opUser 处理人
//memberList 被处理的群成员
}, onGroupAttributeChanged:
(String groupID, Map<String, String> groupAttributeMap) async {
//收到群属性更新的回调
//groupID 群 ID
//groupAttributeMap 群的所有属性
}, onGroupCreated: (String groupID) async {
//创建群(主要用于多端同步)
//groupID 群 ID
}, onGroupDismissed: (String groupID, V2TimGroupMemberInfo opUser) async {
//群被解散了(全员能收到)
//groupID 群 ID
//opUser 处理人
}, onGroupInfoChanged:
(String groupID, List<V2TimGroupChangeInfo> changeInfos) async {
//群信息被修改(全员能收到)
//groupID 群 ID
//changeInfos 修改的群信息
}, onGroupRecycled: (String groupID, V2TimGroupMemberInfo opUser) async {
//群被回收(全员能收到)
//groupID 群 ID
//opUser 处理人
}, onMemberEnter:
(String groupID, List<V2TimGroupMemberInfo> memberList) async {
//有用户加入群(全员能够收到)
//groupID 群 ID
//memberList 加入的成员
}, onMemberInfoChanged: (String groupID,
List<V2TimGroupMemberChangeInfo> v2TIMGroupMemberChangeInfoList) async {
//群成员信息被修改,仅支持禁言通知(全员能收到)。
//groupID 群 ID
//v2TIMGroupMemberChangeInfoList 被修改的群成员信息
}, onMemberInvited: (String groupID, V2TimGroupMemberInfo opUser,
List<V2TimGroupMemberInfo> memberList) async {
//某些人被拉入某群(全员能够收到)
//groupID 群 ID
//opUser 处理人
//memberList 被拉进群成员
}, onMemberKicked: (String groupID, V2TimGroupMemberInfo opUser,
List<V2TimGroupMemberInfo> memberList) async {
//某些人被踢出某群(全员能够收到)
//groupID 群 ID
//opUser 处理人
//memberList 被踢成员
}, onMemberLeave: (String groupID, V2TimGroupMemberInfo member) async {
//有用户离开群(全员能够收到)
//groupID 群 ID
//member 离开的成员
}, onQuitFromGroup: (String groupID) async {
//主动退出群组(主要用于多端同步,直播群(AVChatRoom)不支持)
//groupID 群 ID
}, onReceiveJoinApplication:
(String groupID, V2TimGroupMemberInfo member, String opReason) async {
//有新的加群请求(只有群主或管理员会收到)
//groupID 群 ID
//member 申请人
//opReason 申请原因
}, onReceiveRESTCustomData: (String groupID, String customData) async {
//收到 RESTAPI 下发的自定义系统消息
//groupID 群 ID
//customData 自定义数据
}, onRevokeAdministrator: (String groupID, V2TimGroupMemberInfo opUser,
List<V2TimGroupMemberInfo> memberList) async {
//取消管理员身份
//groupID 群 ID
//opUser 处理人
//memberList 被处理的群成员
}, onTopicCreated: (String groupID, String topicID) async {
//话题创建通知
//groupID 创建话题的群组id
//topicID 创建的话题id
}, onTopicDeleted: (String groupID, List<String> topicIDList) async {
//话题删除通知
//groupID 删除话题的群组id
//topicIDList 删除的话题id列表
}, onTopicInfoChanged: (String groupID, V2TimTopicInfo topicInfo) async {
//话题信息更新通知
//groupID 话题信息更新的群组id
//topicInfo 话题信息更新的属性
});
//添加群组监听器
TencentImSDKPlugin.v2TIMManager.addGroupListener(listener: listener);

移除会话监听器

您可以调用 removeConversationListener(点击查看详情) 移除会话监听器。移除后,您将无法再接收到会话变更事件。 该步骤不是必须的,您可以按照自己的业务逻辑按需调用。
示例代码如下:
conversationManager.removeConversationListener(conversationListener);

发送不更新 lastMessage 的消息

会话列表界面,通常需要展示每个会话的最新一条消息预览及发送时间,此时您可以使用 V2TIMConversationlastMessage 作为数据源实现。但是某些场景下,如果您不希望一些消息(例如系统提示等)显示为会话的最新消息,可以在 sendMessage 时设置 isExcludedFromLastMessagefalse/no
发送消息参考 发送消息
说明
isExcludedFromLastMessage 仅Flutter SDK 4.0.0 及以上版本支持。

交流与反馈

点此进入IM社群,享有专业工程师的支持,解决您的难题