功能描述
用户在登录 App 后,可以像微信或 QQ 那样展示最近会话列表,方便找到目标会话。会话列表如下图所示:
会话列表功能主要分为获取会话列表、处理会话列表更新。本文将为您介绍具体的实现细节。
获取会话列表基础接口
您可以调用
getConversationList
(Android / iOS & Mac / Windows) 获取会话列表。该接口拉取的是本地缓存的会话,如果服务器会话有更新,SDK 内部会自动同步,然后在 V2TIMConversationListener
回调告知客户。用户的会话以列表的形式返回,列表中存储的是
V2TIMConversation
对象。目前 IM SDK 对会话列表的排序规则为:5.5.892 及以后版本, 获取的会话列表默认已经按照会话对象的
orderKey
做了排序。orderKey
值越大,代表该会话排序越靠前。orderKey
字段是整型数,当发送新消息、接收新消息、设置草稿或置顶会话时,会话被激活,orderKey
字段会增大。5.5.892 以前版本,获取的会话列表默认已经按照会话
lastMessage
-> timestamp
做了排序。timestamp
越大,会话越靠前。注意
在某些场景下,可能出现会话的
lastMessage
为空(例如清空会话消息)。如果您使用 5.5.892 以前的 SDK,使用 lastMessage
排序时需要额外处理这种异常。我们建议您升级到 5.5.892 及以后的版本,使用 orderKey
字段排序。您可以使用
getConversationList
实现一次性拉取或分页拉取。参考下文说明。一次性拉取
一次性拉取适合会话数量比较少的情况(100 个以内)。此时可以将拉取的 count 设置为 INT_MAX(一般会话数量不会达到 INT_MAX 这么多)。
示例代码如下:
V2TIMManager.getConversationManager().getConversationList(0, Integer.MAX_VALUE, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {long nextSeq = v2TIMConversationResult.getNextSeq();Log.i("imsdk", "success nextSeq:" + nextSeq + ", isFinish:" + v2TIMConversationResult.isFinished());List<V2TIMConversation> v2TIMConversationList = v2TIMConversationResult.getConversationList();for (V2TIMConversation v2TIMConversation : v2TIMConversationList) {Log.i("imsdk", "success showName:" + v2TIMConversation.getShowName());}}@Overridepublic void onError(int code, String desc) {Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
[[V2TIMManager sharedInstance] getConversationList:0count:INT_MAXsucc:^(NSArray<V2TIMConversation *> *list, uint64_t lastTS, BOOL isFinished) {// 获取成功,list 为会话列表} fail:^(int code, NSString *msg) {// 获取失败}];
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};uint64_t nextSeq = 0;uint32_t count = std::numeric_limits<uint32_t>::max();auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationList(nextSeq, count, callback);
分页拉取
如果您的应用场景会产生较多的会话数,考虑到加载效率、网络省流,我们建议您采用分页拉取的方式。每次分页拉取的数量建议不超过 100 个。
分页拉取的步骤:
1. 首次调用
getConversationList
时,指定参数 nextSeq
为 0(表示从头开始拉取会话列表),指定 count
为 50(表示一次拉取 50 个会话对象)。2. 首次拉取会话列表成功后,
getConversationList
的回调结果 V2TIMConversationResult
中会包含 nextSeq
(下次分页拉取的字段)、isFinish
(会话拉取是否完成)。如果
isFinished
为 true
,表示所有会话已经拉取完成。如果
isFinished
为 false
,表示还有更多的会话可以拉取。此时并不意味着要立刻开始拉取 “下一页” 的会话列表。在常见的软件中,分页拉取通常由用户的滑动操作触发的,用户每上拉一次会话列表就触发一次分页拉取。3. 当用户继续上拉会话列表时,如果还有更多的会话可以拉取,可以继续调用
getConversationList
接口,并传入新一轮的 nextSeq
(数值来自上一次拉取返回的 V2TIMConversationResult
对象)和 count
参数。4. 重复执行【步骤 3】直至
isFinished
返回 true。示例代码如下:
V2TIMManager.getConversationManager().getConversationList(0, 20, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {long nextSeq = v2TIMConversationResult.getNextSeq();Log.i("imsdk", "success nextSeq:" + nextSeq + ", isFinish:" + v2TIMConversationResult.isFinished());List<V2TIMConversation> v2TIMConversationList = v2TIMConversationResult.getConversationList();for (V2TIMConversation v2TIMConversation : v2TIMConversationList) {Log.i("imsdk", "success showName:" + v2TIMConversation.getShowName());}if (!v2TIMConversationResult.isFinished()) {getConversationListInternal(nextSeq, 20);}}@Overridepublic void onError(int code, String desc) {Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
// 用户上拉会话列表到底部,没有更多会话数据展示时触发- (void)loadConversation {if (self.isFinished) {return;}@weakify(self)[[V2TIMManager sharedInstance] getConversationList:self.nextSeqcount:20 // 每次拉 20 个会话succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {// 拉取成功@strongify(self)// 更新下一次拉取的锚点 nextSeq 和是否完成拉取标识位 isFinishedself.nextSeq = nextSeq;self.isFinished = isFinished;// 用 list 更新 UI} fail:^(int code, NSString *msg) {// 拉取失败,结束本次拉取self.isFinished = YES;}];}
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};uint64_t nextSeq = 0;uint32_t count = 20;auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功if (!conversationResult.isFinished) {nextSeq = conversationResult.nextSeq;// 继续获取 ...}delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationList(nextSeq, count, callback);
获取会话列表高级接口
如果以上的普通接口无法满足您对拉取会话列表的需求,我们还提供了高级接口
getConversationListByFilter
(Android / iOS & Mac / Windows),其中拉取会话的 V2TIMConversationListFilter
详解如下:拉取单聊或群聊会话
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();filter.setConversationType(V2TIMConversation.V2TIM_C2C); //拉取单聊会话// filter.setConversationType(V2TIMConversation.V2TIM_GROUP); //拉取群聊会话V2TIMManager.getConversationManager().getConversationListByFilter(filter, 0, 50, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {// 获取会话列表成功}@Overridepublic void onError(int code, String desc) {// 获取会话列表失败}});
V2TIMConversationListFilter *filter = [[V2TIMConversationListFilter alloc] init];filter.type = V2TIM_C2C; //拉取单聊会话// filter.type = V2TIM_GROUP; //拉取群聊会话[[V2TIMManager sharedInstance] getConversationListByFilter:filter nextSeq:0 count:50 succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {// 获取会话列表成功,list 为会话列表} fail:^(int code, NSString *desc) {// 获取会话列表失败}];
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};V2TIMConversationListFilter filter;filter.type = V2TIMConversationType::V2TIM_C2C; // 拉取单聊会话// filter.type = V2TIMConversationType::V2TIM_GROUP; //拉取群聊会话auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationListByFilter(filter, 0, 50, callback);
拉取指定分组会话
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();filter.setConversationGroup("conversation_group");V2TIMManager.getConversationManager().getConversationListByFilter(filter, 0, 50, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {// 获取会话列表成功}@Overridepublic void onError(int code, String desc) {// 获取会话列表失败}});
V2TIMConversationListFilter *filter = [[V2TIMConversationListFilter alloc] init];filter.conversationGroup = @"conversation_group";[[V2TIMManager sharedInstance] getConversationListByFilter:filter nextSeq:0 count:50 succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {// 获取会话列表成功,list 为会话列表} fail:^(int code, NSString *desc) {// 获取会话列表失败}];
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};V2TIMConversationListFilter filter;filter.conversationGroup = u8"conversation_group";auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationListByFilter(filter, 0, 50, callback);
拉取指定标记会话
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();filter.setMarkType(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_STAR);V2TIMManager.getConversationManager().getConversationListByFilter(filter, 0, 50, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {// 获取会话列表成功}@Overridepublic void onError(int code, String desc) {// 获取会话列表失败}});
V2TIMConversationListFilter *filter = [[V2TIMConversationListFilter alloc] init];filter.markType = V2TIM_CONVERSATION_MARK_TYPE_STAR;[[V2TIMManager sharedInstance] getConversationListByFilter:filter nextSeq:0 count:50 succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {// 获取会话列表成功,list 为会话列表} fail:^(int code, NSString *desc) {// 获取会话列表失败}];
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};V2TIMConversationListFilter filter;filter.markType = V2TIMConversationMarkType::V2TIM_CONVERSATION_MARK_TYPE_STAR;auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationListByFilter(filter, 0, 50, callback);
拉取含有未读数的会话
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();filter.setHasUnreadCount(true);V2TIMManager.getConversationManager().getConversationListByFilter(filter, 0, 50, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {// 获取会话列表成功}@Overridepublic void onError(int code, String desc) {// 获取会话列表失败}});
V2TIMConversationListFilter *filter = [[V2TIMConversationListFilter alloc] init];filter.hasUnreadCount = YES;[[V2TIMManager sharedInstance] getConversationListByFilter:filter nextSeq:0 count:50 succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {// 获取会话列表成功,list 为会话列表} fail:^(int code, NSString *desc) {// 获取会话列表失败}];
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};V2TIMConversationListFilter filter;filter.hasUnreadCount = true;auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationListByFilter(filter, 0, 50, callback);
拉取含有群 @ 消息的会话
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();filter.setHasGroupAtInfo(true);V2TIMManager.getConversationManager().getConversationListByFilter(filter, 0, 50, new V2TIMValueCallback<V2TIMConversationResult>() {@Overridepublic void onSuccess(V2TIMConversationResult v2TIMConversationResult) {// 获取会话列表成功}@Overridepublic void onError(int code, String desc) {// 获取会话列表失败}});
V2TIMConversationListFilter *filter = [[V2TIMConversationListFilter alloc] init];filter.hasGroupAtInfo = YES;[[V2TIMManager sharedInstance] getConversationListByFilter:filter nextSeq:0 count:50 succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {// 获取会话列表成功,list 为会话列表} fail:^(int code, NSString *desc) {// 获取会话列表失败}];
template <class T>class ValueCallback final : public V2TIMValueCallback<T> {public:using SuccessCallback = std::function<void(const T&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;ValueCallback() = default;~ValueCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);}void OnSuccess(const T& value) override {if (success_callback_) {success_callback_(value);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;};V2TIMConversationListFilter filter;filter.hasGroupAtInfo = true;auto callback = new ValueCallback<V2TIMConversationResult>{};callback->SetCallback([=](const V2TIMConversationResult& conversationResult) {// 获取会话列表成功delete callback;},[=](int error_code, const V2TIMString& error_message) {// 获取会话列表失败delete callback;});V2TIMManager::GetInstance()->GetConversationManager()->GetConversationListByFilter(filter, 0, 50, callback);
会话列表排序
会话列表始终按照 V2TIMConversation.orderKey 从大到小的顺序排列,orderKey 会随着会话的更新依次递增。
常见引起 orderKey 递增的操作有:收发消息(也即 lastMessage 发生变化)、置顶/取消置顶。
当会话的 lastMessage 的时间顺序与 orderKey 不一致时,以 orderKey 顺序为准。
会话列表更新
IM SDK 会在登录成功后、用户上线后、以及断线重连后,自动更新会话列表。
为了获取会话列表的更新,您需要操作如下几步:
1. 添加会话监听器。
2. 接收会话变更通知并处理。
3. 移除会话监听器。非必须,可按照业务逻辑按需调用。
添加会话监听器
示例代码如下:
V2TIMManager.getConversationManager().addConversationListener(conversationListener);
// self 为 id<V2TIMConversationListener> 类型[[V2TIMManager sharedInstance] addConversationListener:self];
class ConversationListener final : public V2TIMConversationListener {// 成员 ...};// 添加会话事件监听器,注意在移除监听器之前需要保持 conversationListener 的生命期,以免接收不到事件回调ConversationListener conversationListener;V2TIMManager::GetInstance()->GetConversationManager()->AddConversationListener(&conversationListener);
会话新增变更通知
目前 IM SDK 支持的会话变更事件有:
事件 | 说明 | 建议 |
onSyncServerStart | 同步服务器会话开始 | SDK 会在登录成功、用户上线、断网重连后自动同步服务器会话,您可以监听这个事件做一些 UI 进度展示操作。 |
onSyncServerFinish | 同步服务器会话完成 | 如果会话有变更,会通过 onNewConversation /onConversationChanged 回调告知。 |
onSyncServerFailed | 同步服务器会话失败 | 您可以监听这个事件做一些 UI 异常展示操作。 |
onNewConversation | 有会话新增 | 例如收到一个新同事发来的单聊消息、被拉入了一个新的群组中等,此时可以重新对会话列表做排序。 |
onConversationChanged | 有会话更新 | 例如未读计数发生变化、最后一条消息被更新等,此时可以重新对会话列表做排序。 |
onConversationDeleted | 有会话被删除 | |
onTotalUnreadMessageCountChanged | 会话未读总数变更通知 | |
onUnreadMessageCountChangedByFilter | 过滤条件下未读总数变更通知 |
注意
1. 为保证会话列表顺序符合最后一条消息的排序原则,每次会话变更/新增后,您需要对数据源重新排序。
如果您使用 5.5.892 以前的版本,可以使用
lastMessage
排序,但是需要注意处理 lastMessage
为空(例如清空会话消息)的情况。如果您使用 5.5.892 及以后的版本,使用
orderKey
字段排序。我们强烈建议您升级到 5.5.892 及以后版本。2. 调用
getConversationList
接口拉取的会话可能已经通过 onNewConversation
回调接口添加到了 UI 会话列表的数据源中。为了避免重复添加同一个会话,您需要在 UI 会话列表数据源中根据 getConversationID
找到相同的会话并做替换。示例代码如下:
// 监听会话的回调V2TIMConversationListener conversationListener = new V2TIMConversationListener() {@Overridepublic void onSyncServerStart() {Log.i("imsdk", "onSyncServerStart");}@Overridepublic void onSyncServerFinish() {Log.i("imsdk", "onSyncServerFinish");}@Overridepublic void onSyncServerFailed() {Log.i("imsdk", "onSyncServerFailed");}@Overridepublic void onNewConversation(List<V2TIMConversation> conversationList) {Log.i("imsdk", "onNewConversation");}@Overridepublic void onConversationChanged(List<V2TIMConversation> conversationList) {Log.i("imsdk", "onConversationChanged");}@Overridepublic void onConversationDeleted(List<String> conversationIDList) {Log.i("imsdk", "onConversationDeleted");}@Overridepublic void onTotalUnreadMessageCountChanged(long totalUnreadCount) {Log.i("imsdk", "onTotalUnreadMessageCountChanged");}@Overridepublic void onUnreadMessageCountChangedByFilter(V2TIMConversationListFilter filter, long totalUnreadCount) {Log.i("imsdk", "onUnreadMessageCountChangedByFilter");}};
- (void)onSyncServerStart {// 同步服务器会话开始}- (void)onSyncServerFinish {// 同步服务器会话结束}- (void)onSyncServerFailed {// 同步服务器会话失败}- (void)onNewConversation:(NSArray<V2TIMConversation*> *)conversationList {// 收到会话新增通知,conversationList 为新增的会话[self updateConversation:conversationList];}- (void)onConversationChanged:(NSArray<V2TIMConversation*> *)conversationList {// 收到会话变更通知,conversationList 中为变更后的会话对象[self updateConversation:conversationList];}- (void)onConversationDeleted:(NSArray<NSString *> *)conversationIDList {// 会话被删除}- (void)onTotalUnreadMessageCountChanged:(UInt64) totalUnreadCount {// 会话未读总数变化}- (void)onUnreadMessageCountChangedByFilter:(V2TIMConversationListFilter *)filter totalUnreadCount:(UInt64)totalUnreadCount {// 过滤条件下的会话未读总数变化}- (void)updateConversation:(NSArray *)convList {// 更新 UI 会话列表,如果 UI 会话列表已经存在该新增/变更的会话,就替换之;如果没有,就新增一个会话对象for (int i = 0 ; i < convList.count ; ++ i) {V2TIMConversation *conv = convList[i];BOOL isExit = NO;for (int j = 0; j < self.localConvList.count; ++ j) {V2TIMConversation *localConv = self.localConvList[j];if ([localConv.conversationID isEqualToString:conv.conversationID]) {// UI 会话列表有更新的会话,直接替换[self.localConvList replaceObjectAtIndex:j withObject:conv];isExit = YES;break;}}// UI 会话列表没有更新的会话,直接新增if (!isExit) {[self.localConvList addObject:conv];}}// 重新对 UI 会话列表做排序[self sortDataList:dataList];self.dataList = dataList;}
class ConversationListener final : public V2TIMConversationListener {public:ConversationListener() = default;~ConversationListener() override = default;void OnSyncServerStart() override {// 同步服务器会话开始}void OnSyncServerFinish() override {// 同步服务器会话结束}void OnSyncServerFailed() override {// 同步服务器会话失败}void OnNewConversation(const V2TIMConversationVector& conversationList) override {// 收到会话新增通知}void OnConversationChanged(const V2TIMConversationVector& conversationList) override {// 收到会话变更通知}void OnConversationDeleted(const V2TIMStringVector &conversationIDList) override {// 收到会话被删除通知}void OnTotalUnreadMessageCountChanged(uint64_t totalUnreadCount) override {// 会话未读总数变更通知}void OnUnreadMessageCountChangedByFilter(const V2TIMConversationListFilter &filter, uint64_t totalUnreadCount) {// 过滤条件下会话未读总数变更通知}};// 添加会话事件监听器,注意在移除监听器之前需要保持 conversationListener 的生命期,以免接收不到事件回调ConversationListener conversationListener;V2TIMManager::GetInstance()->GetConversationManager()->AddConversationListener(&conversationListener);
移除会话监听器
您可以调用
removeConversationListener
(Android / iOS & Mac / Windows )移除会话监听器。移除后,您将无法再接收到会话变更事件。
该步骤不是必须的,您可以按照自己的业务逻辑按需调用。示例代码如下:
V2TIMManager.getConversationManager().removeConversationListener(conversationListener);
// self 为 id<V2TIMConversationListener> 类型[[V2TIMManager sharedInstance] removeConversationListener:self];
class ConversationListener final : public V2TIMConversationListener {// 成员 ...};// conversationListener 是 ConversationListener 的实例V2TIMManager::GetInstance()->GetConversationManager()->RemoveConversationListener(&conversationListener);
发送不更新 lastMessage 的消息
会话列表界面,通常需要展示每个会话的最新一条消息预览及发送时间,此时您可以使用
V2TIMConversation
的 lastMessage
作为数据源实现。
但是某些场景下,如果您不希望一些消息(例如系统提示等)显示为会话的最新消息,可以在 sendMessage
时设置 isExcludedFromLastMessage
为 false
/NO
。说明
isExcludedFromLastMessage
参数仅增强版 SDK 5.4.666 及以上版本支持。示例代码如下:
// 创建消息对象V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createTextMessage(content);// 设置不更新会话 lastMessagev2TIMMessage.setExcludedFromLastMessage(true);// 发送消息V2TIMManager.getMessageManager().sendMessage(v2TIMMessage, "userID", null, V2TIMMessage.V2TIM_PRIORITY_DEFAULT, false, null, new V2TIMSendCallback<V2TIMMessage>() {@Overridepublic void onSuccess(V2TIMMessage v2TIMMessage) {Log.i("imsdk", "success");}@Overridepublic void onProgress(int progress) {Log.i("imsdk", "progress:" + progress);}@Overridepublic void onError(int code, String desc) {Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);}});
// 创建消息对象V2TIMMessage *message = [V2TIMManager.sharedInstance createTextMessage:content];// 设置不计入会话 lastMessage 的标记message.isExcludedFromLastMessage = YES;// 发送消息[V2TIMManager.sharedInstance sendMessage:messagereceiver:@"userA"groupID:nilpriority:V2TIM_PRIORITY_NORMALonlineUserOnly:NOofflinePushInfo:nilprogress:^(uint32_t progress) {// 发送进度} succ:^{// 消息发送成功} fail:^(int code, NSString *desc) {// 消息发送失败}];
class SendCallback final : public V2TIMSendCallback {public:using SuccessCallback = std::function<void(const V2TIMMessage&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;using ProgressCallback = std::function<void(uint32_t)>;SendCallback() = default;~SendCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback,ProgressCallback progress_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);progress_callback_ = std::move(progress_callback);}void OnSuccess(const V2TIMMessage& message) override {if (success_callback_) {success_callback_(message);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}void OnProgress(uint32_t progress) override {if (progress_callback_) {progress_callback_(progress);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;ProgressCallback progress_callback_;};// 创建消息对象V2TIMMessage message = V2TIMManager::GetInstance()->GetMessageManager()->CreateTextMessage(u8"content");// 设置不更新会话 lastMessagemessage.isExcludedFromLastMessage = true;auto callback = new SendCallback{};callback->SetCallback([=](const V2TIMMessage& message) { delete callback; },[=](int error_code, const V2TIMString& error_message) { delete callback; },[=](uint32_t progress) {});V2TIMManager::GetInstance()->GetMessageManager()->SendMessage(message, u8"userID", {}, V2TIMMessagePriority::V2TIM_PRIORITY_NORMAL, false, {}, callback);