流式消息
本文介绍如何在 Flutter IMLib SDK 中接收并拉取流式消息,涵盖消息监听、拉取流程、事件回调与摘要获取等内容。
此功能从 5.32.0 版本开始支持。
流式消息简介
流式消息由业务服务器触发,融云 IM 服务器会以多次推送的形式将数据片段下发到客户端。客户端首先通过 onMessageReceived 收到一条 RCIMIWStreamMessage,再调用 requestStreamMessageContent 拉取完整内容,并通过流式事件监听器按 init > data > complete 顺序获取生成过程。
Flutter SDK 仅负责接收和拉取流式消息,不提供发送流式消息的接口。
下图展示了完整的交互流程:
RCIMIWStreamMessage 继承自 RCIMIWMessage,关键字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
content | String? | 首包携带的流式内容片段 |
type | String? | 服务器自定义的文本格式描述,例如 text/plain |
complete | bool? | 是否已生成完毕 |
sync | bool? | 客户端是否已完成完整拉取,false 时需主动调用 requestStreamMessageContent |
completeReason | int? | 业务侧定义的结束原因码 |
stopReason | int? | 服务器定义的结束原因,0 代表正常结束 |
referMsg | RCIMIWReferenceInfo? | 流式消息引用的原消息信息 |
接收流式消息
SDK 不支持发送流式消息,需要由服务器触发。当收到流式消息时,可在 onMessageReceived 回调中判断消息类型,并根据 sync 字段决定是否发起拉取:
engine?.onMessageReceived = (RCIMIWMessage? message, int? left, bool? offline, bool? hasPackage) {
if (message?.content is RCIMIWStreamMessage) {
final streamMsg = message!.content as RCIMIWStreamMessage;
if (streamMsg.sync == false) {
debugPrint('收到流式消息 ${message.messageUId},需要继续拉取');
} else {
debugPrint('流式消息已同步完成,无需重复拉取');
}
}
};
历史流式消息
SDK 接收到流式消息后,会存储到本地数据库。开发者在调用获取历史消息相关接口时,可以查询到流式消息。
拉取流式消息
监听拉取事件
在调用 requestStreamMessageContent 之前,先设置流式拉取事件监听,分别处理初始化、增量数据与完成事件:
engine?.onStreamMessageRequestInit = (String? messageUId) {
debugPrint('init => $messageUId');
};
engine?.onStreamMessageRequestData = (
RCIMIWMessage? message,
RCIMIWStreamMessageChunkInfo? chunkInfo,
) {
debugPrint('chunk => ${message?.messageUId}, data=${chunkInfo?.content}');
};
engine?.onStreamMessageRequestComplete = (String? messageUId, int? code) {
debugPrint('complete => $messageUId, code=$code');
};
事件说明
| 回调 | 参数 | 说明 |
|---|---|---|
onStreamMessageRequestInit | messageUId | 请求准备完成,若之前异常中止会清理旧数据 |
onStreamMessageRequestData | message, chunkInfo | 每次收到一个增量片段,chunkInfo.content 为片段内容 |
onStreamMessageRequestComplete | messageUId, code | 拉取结束,code 为完成原因,非 0 时可结合消息 completeReason、stopReason 排查异常 |
发起拉取
开发者在获取到流式消息后,可以通过 sync 参数判断流式消息是否已经同步完成。如果为 false,开发者可以按需拉取流式消息。
接口
requestStreamMessageContent(
RCIMIWStreamMessageRequestParams params,
{IRCIMIWOperationCallback? callback}
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
params | RCIMIWStreamMessageRequestParams | 请求参数,仅需传入 messageUId |
callback | IRCIMIWOperationCallback? | 表示请求是否成功发起,真正的数据通过事件监听返回 |
RCIMIWStreamMessageRequestParams 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
messageUId | String? | 目标流式消息的唯一 ID(必填) |
示例代码
final params = RCIMIWStreamMessageRequestParams.create(messageUId: messageUId);
final IRCIMIWOperationCallback callback = IRCIMIWOperationCallback(
onSuccess: () => debugPrint('流式消息拉取请求已受理'),
onError: (int? code) => debugPrint('流式消息拉取失败: $code'),
);
await IMEngineManager().engine?.requestStreamMessageContent(params, callback: callback);
IRCIMIWOperationCallback 仅表示请求是否成功进入服务端流程,真正的流式内容请使用事件监听(onStreamMessageRequest…)获取。
获取流式消息摘要
当服务器完成流式内容生成后,会通过消息扩展的方式写入摘要(默认 key:RC_Ext_StreamMsgSummary)。您可以使用消息扩展监听或直接读取消息体上的 expansion 获取摘要。
监听消息扩展更新
engine?.onRemoteMessageExpansionUpdated = (Map? expansion, RCIMIWMessage? message) {
if (message?.content is RCIMIWStreamMessage) {
final summary = expansion?['RC_Ext_StreamMsgSummary'];
if (summary != null) {
debugPrint('实时收到流式摘要: $summary');
}
}
};
读取历史摘要
消息扩展会存储在本地数据库,可结合 RCIMIWStreamMessage.complete 判断,直接从消息实体的 expansion map 中读取:
if (message.content is RCIMIWStreamMessage) {
final streamMsg = message.content as RCIMIWStreamMessage;
if (streamMsg.complete == true) {
final summary = message.expansion?['RC_Ext_StreamMsgSummary'];
debugPrint('历史流式摘要: $summary');
}
}