跳到主要内容

消息回应

消息回应(Message Reaction)允许用户对已发送成功的消息添加、取消表情回应,并查询回应信息。应用可以使用这些数据自行展示回应按钮、人数和用户列表。

前置条件​

  • 使用 Flutter IMLib 5.44.1 或更高版本,完成 SDK 初始化并连接 IM。
  • 支持单聊、群聊和超级群会话。
  • 使用消息的服务器唯一 ID messageUId;发送中、发送失败或尚未获得有效 UID 的消息不能添加回应。
  • reactionId 是非空的回应标识,例如 👍。同一种回应在各端应使用相同标识,长度不能超过 16(按 SDK 字符串长度计,不是字节数)。

功能概览​

功能Flutter 接口
添加回应addMessageReaction
移除回应removeMessageReaction
批量查询消息回应摘要batchGetMessageReactionSummaries
分页查询一条消息的回应列表getMessageReactions
分页查询指定回应的用户列表getMessageReactionUsers
监听回应变化onMessageReactionChanged

以下五个接口均返回 Future<int>。await 得到的 0 表示本次调用已受理,最终业务结果通过 callback 返回;即时返回非 0 时不会触发该次回调。示例均传入回调,回调对象的 onSuccess 和 onError 必须同时提供。示例中的类型来自 package:rongcloud_im_wrapper_plugin/rongcloud_im_wrapper_plugin.dart。

添加回应​

调用 addMessageReaction 为消息添加回应。同一用户不能对同一条消息重复添加相同的 reactionId;一条消息最多包含 50 个回应信息,超过限制时通过错误回调返回状态码。

参数说明​

参数类型说明
paramRCIMIWUpdateMessageReactionParam使用 .create(...) 构造添加参数。
callbackIRCIMIWOperationCallback?onSuccess() 表示添加成功,onError(int? code) 返回错误码。

RCIMIWUpdateMessageReactionParam 字段如下。模型字段在 Dart 中可空,但 messageUId 和 reactionId 调用时必须填写有效值。

字段类型说明
messageUIdString?消息服务器 UID。
reactionIdString?要添加的回应 ID。
pushOptionsRCIMIWMessagePushOptions?可选的回应操作推送配置;Flutter 字段名为 pushOptions。

示例代码​

Dart
Future<int> addReaction(
RCIMIWEngine engine,
String messageUId,
String reactionId, {
RCIMIWMessagePushOptions? pushOptions,
}) async {
final param = RCIMIWUpdateMessageReactionParam.create(
messageUId: messageUId,
reactionId: reactionId,
pushOptions: pushOptions,
);
final code = await engine.addMessageReaction(
param,
callback: IRCIMIWOperationCallback(
onSuccess: () => print('添加回应成功'),
onError: (errorCode) => print('添加回应失败:$errorCode'),
),
);
if (code != 0) print('接口调用失败:$code');
return code;
}

移除回应​

调用 removeMessageReaction 移除当前用户已添加的回应。reactionId 应与添加时使用的标识一致。

参数说明​

参数类型说明
paramRCIMIWUpdateMessageReactionParam使用 .create(...) 构造移除参数。
callbackIRCIMIWOperationCallback?onSuccess() 表示移除成功,onError(int? code) 返回错误码。

移除参数与添加参数使用同一模型:

字段类型说明
messageUIdString?必填,消息服务器 UID。
reactionIdString?必填,当前用户要移除的回应 ID。
pushOptionsRCIMIWMessagePushOptions?可选的回应操作推送配置。

示例代码​

Dart
Future<int> removeReaction(
RCIMIWEngine engine,
String messageUId,
String reactionId,
) async {
final code = await engine.removeMessageReaction(
RCIMIWUpdateMessageReactionParam.create(
messageUId: messageUId,
reactionId: reactionId,
),
callback: IRCIMIWOperationCallback(
onSuccess: () => print('移除回应成功'),
onError: (errorCode) => print('移除回应失败:$errorCode'),
),
);
if (code != 0) print('接口调用失败:$code');
return code;
}

批量查询回应摘要​

调用 batchGetMessageReactionSummaries 一次查询同一会话内多条消息的回应摘要,适合在加载消息列表后补齐回应展示。

参数说明​

参数类型说明
paramRCIMIWMessageReactionSummaryQueryParam摘要查询条件,使用 .create(...) 构造。
callbackIRCIMIWBatchGetMessageReactionSummariesCallback?onSuccess 返回 Map<String, List<RCIMIWMessageReaction>>?;onError(int? code) 返回错误码。

RCIMIWMessageReactionSummaryQueryParam 直接包含以下字段,不需要额外构造原生 ConversationIdentifier:

字段类型说明
conversationTypeRCIMIWConversationType?必填,会话类型。
targetIdString?必填,会话 ID。
channelIdString?频道 ID,普通会话传 null,超级群传对应频道 ID。
messageUIdsList<String>?必填,属于上述会话的有效消息 UID 列表,单次 1 到 100 条。

结果 Map 的 key 是 messageUId,value 是该消息的回应摘要列表。Map 为空、缺少某个 UID,或对应列表为空时,界面应按“无可见回应”处理。

示例代码​

Dart
Future<int> queryReactionSummaries(
RCIMIWEngine engine,
RCIMIWConversationType type,
String targetId,
List<String> messageUIds, {
String? channelId,
}) async {
final code = await engine.batchGetMessageReactionSummaries(
RCIMIWMessageReactionSummaryQueryParam.create(
conversationType: type,
targetId: targetId,
channelId: channelId,
messageUIds: messageUIds,
),
callback: IRCIMIWBatchGetMessageReactionSummariesCallback(
onSuccess: (result) {
for (final messageUId in messageUIds) {
final reactions = result?[messageUId] ?? <RCIMIWMessageReaction>[];
// 按 messageUId 更新界面;空列表表示无可见回应。
for (final reaction in reactions) {
print('${reaction.reactionId}: ${reaction.totalCount ?? 0}');
}
}
},
onError: (errorCode) => print('查询摘要失败:$errorCode'),
),
);
if (code != 0) print('接口调用失败:$code');
return code;
}

摘要和回应列表中的 RCIMIWMessageReaction 字段如下:

字段类型说明
messageUIdString?消息 UID。
reactionIdString?回应 ID。
hasCurrentUserReactedbool?当前用户是否已添加该回应。
usersList<RCIMIWMessageReactionUser>?部分回应用户;完整用户列表需要调用 getMessageReactionUsers 分页查询。
totalCountint?该回应的总人数。
reactionTimeint?回应时间,单位为毫秒。

分页查询回应列表​

调用 getMessageReactions 查询一条消息上的回应列表。

参数说明​

参数类型说明
paramRCIMIWGetMessageReactionsParam分页条件,使用 .create(...) 构造。
callbackIRCIMIWGetMessageReactionsCallback?onSuccess 返回 RCIMIWPagingQueryResult<RCIMIWMessageReaction>?;onError(int? code) 返回错误码。

RCIMIWGetMessageReactionsParam 字段如下:

字段类型说明
messageUIdString?必填,消息 UID。
countint?必填,每页数量,范围为 1 到 50。
pageTokenString?首次查询传 null,下一页传上次结果中的 pageToken。

示例代码​

Dart
Future<int> queryReactionsPage(
RCIMIWEngine engine,
String messageUId,
void Function(List<RCIMIWMessageReaction>, String?) onPage, {
String? pageToken,
}) async {
final code = await engine.getMessageReactions(
RCIMIWGetMessageReactionsParam.create(
messageUId: messageUId,
count: 50,
pageToken: pageToken,
),
callback: IRCIMIWGetMessageReactionsCallback(
onSuccess: (result) {
final reactions = result?.data ?? <RCIMIWMessageReaction>[];
final token = result?.pageToken;
final nextToken = token == null || token.isEmpty ? null : token;
onPage(reactions, nextToken);
// nextToken 非 null 时,可在下一次调用中作为 pageToken 传入。
},
onError: (errorCode) => print('查询回应失败:$errorCode'),
),
);
if (code != 0) print('接口调用失败:$code');
return code;
}

分页结果 RCIMIWPagingQueryResult<T> 包含 data(本页数据)、totalCount(总数)和 pageToken(下一页标识)。这三个字段均可空;pageToken 为 null 或空字符串时结束分页,不要再次用 null 请求下一页,否则会重新查询第一页。后续请求应原样复用返回的 token,不要自行解析或构造。

分页查询回应用户列表​

调用 getMessageReactionUsers 查询某条消息中添加了指定回应的用户。

参数说明​

参数类型说明
paramRCIMIWGetMessageReactionUsersParam用户查询条件,使用 .create(...) 构造。
callbackIRCIMIWGetMessageReactionUsersCallback?onSuccess 返回 RCIMIWPagingQueryResult<RCIMIWMessageReactionUser>?;onError(int? code) 返回错误码。

RCIMIWGetMessageReactionUsersParam 字段如下:

字段类型说明
messageUIdString?必填,消息 UID。
reactionIdString?必填,需要查询用户的回应 ID。
countint?必填,每页数量,范围为 1 到 50。
pageTokenString?首次查询传 null,后续使用上次返回的 pageToken。

示例代码​

Dart
Future<int> queryReactionUsersPage(
RCIMIWEngine engine,
String messageUId,
String reactionId,
void Function(List<RCIMIWMessageReactionUser>, String?) onPage, {
String? pageToken,
}) async {
final code = await engine.getMessageReactionUsers(
RCIMIWGetMessageReactionUsersParam.create(
messageUId: messageUId,
reactionId: reactionId,
count: 50,
pageToken: pageToken,
),
callback: IRCIMIWGetMessageReactionUsersCallback(
onSuccess: (result) {
final users = result?.data ?? <RCIMIWMessageReactionUser>[];
final token = result?.pageToken;
final nextToken = token == null || token.isEmpty ? null : token;
onPage(users, nextToken);
},
onError: (errorCode) => print('查询回应用户失败:$errorCode'),
),
);
if (code != 0) print('接口调用失败:$code');
return code;
}

分页终止条件与回应列表相同。RCIMIWMessageReactionUser 包含:

字段类型说明
userIdString?添加回应的用户 ID。
reactionTimeint?该用户添加回应的时间,单位为毫秒。

监听回应变更​

设置 engine.onMessageReactionChanged 接收当前用户或其他用户触发的回应变更。回调可能一次返回多个事件;事件所属会话由 conversationType、targetId 和 channelId 标识,业务应只更新对应会话的界面或缓存。

RCIMIWMessageReactionEvent 字段如下:

字段类型说明
conversationTypeRCIMIWConversationType?会话类型。
targetIdString?会话 ID。
channelIdString?频道 ID。
messageUIdString?发生变更的消息 UID。
reactionIdString?回应 ID;清空整条消息的回应时可能为空。
operationTypeRCIMIWMessageReactionOperationType?added(添加)、removed(移除)、cleared(清除)。
usersList<RCIMIWMessageReactionUser>?本次变更相关用户,不等同于完整用户列表。
totalCountint?该回应变更后的总人数;清空时为 0。

cleared 的原生语义是清除回应:reactionId 为空时清空整条消息的全部回应,非空时只清除指定回应。清除事件中的 users 可能为空,不要通过用户列表推算清除范围。

5.44.1 事件处理

当前 Flutter 5.44.1 对 operationType 的数值转换存在偏移,暂不建议按该枚举直接增删本地回应。下面的示例收到任意变更后,按消息 UID 重新查询摘要;以查询结果刷新界面,空结果则清空展示,可同时处理添加、移除和清除。

Dart
void observeMessageReactions(
RCIMIWEngine engine,
RCIMIWConversationType type,
String targetId,
void Function(String messageUId, List<RCIMIWMessageReaction>) updateReactions, {
String? channelId,
}) {
engine.onMessageReactionChanged = (events) async {
final messageUIds = <String>{};
for (final event in events ?? <RCIMIWMessageReactionEvent>[]) {
final messageUId = event.messageUId;
if (event.conversationType == type &&
event.targetId == targetId &&
(event.channelId ?? '') == (channelId ?? '') &&
messageUId != null && messageUId.isNotEmpty) {
messageUIds.add(messageUId);
}
}
final ids = messageUIds.toList();
// 批量摘要接口每次最多接收 100 个消息 UID。
for (var start = 0; start < ids.length; start += 100) {
final end = start + 100 < ids.length ? start + 100 : ids.length;
final batch = ids.sublist(start, end);
final code = await engine.batchGetMessageReactionSummaries(
RCIMIWMessageReactionSummaryQueryParam.create(
conversationType: type,
targetId: targetId,
channelId: channelId,
messageUIds: batch,
),
callback: IRCIMIWBatchGetMessageReactionSummariesCallback(
onSuccess: (result) {
for (final id in batch) {
updateReactions(id, result?[id] ?? <RCIMIWMessageReaction>[]);
}
},
onError: (errorCode) => print('刷新回应失败:$errorCode'),
),
);
if (code != 0) print('刷新接口调用失败:$code');
}
};
}

void stopObservingMessageReactions(RCIMIWEngine engine) {
engine.onMessageReactionChanged = null;
}

该属性是全局单一监听入口,重复赋值会替换原监听。页面销毁时,只清理自己负责的监听;多个页面共享同一引擎时,建议由应用统一接收并分发事件。

hasReactions 字段​

RCIMIWMessage.hasReactions 是 SDK 维护的回应提示字段,不是完整回应列表。值为 true 时,可以按需查询回应摘要:

Dart
bool shouldQueryReactionSummary(RCIMIWMessage message) {
return message.hasReactions == true;
}

添加回应成功后,该字段会更新为 true。移除单个回应时,本地数据可能不完整,SDK 不会直接据此将字段改为 false;收到服务端清空通知后才更新为 false。若字段为 true,但摘要查询返回空结果,界面应展示为“无可见回应”,不要只根据该字段长期保留回应按钮或人数。

状态码​

返回位置状态处理方式
Future<int> 即时返回值0请求已受理,继续等待结果回调。
Future<int> 即时返回值非 0本次调用失败,例如参数无效或引擎已销毁;不会触发该次结果回调。
callback.onError错误码受理后的操作或查询失败,按回调错误码处理。
callback.onError26323消息回应数量达到上限。
callback.onError26324指定回应的用户数达到上限。

其他错误码及平台定义请参考状态码。onSuccess 中的可空 Map、分页结果及列表字段应按示例判空后使用。