Streaming messages
This guide covers how to receive and fetch streaming messages in the Flutter Chat SDK, including message listeners, fetch flow, event callbacks, and summary retrieval.
Overview
Streaming messages are triggered by your app server. The Nexconn server delivers data fragments to the client through multiple pushes. The client first receives a StreamMessage via onMessageReceived, then calls requestStreamMessageContent to fetch the full content. The streaming event listener delivers events in the order init > data > complete.
The Flutter SDK only receives and fetches streaming messages. It does not provide an API to send streaming messages.
The following diagram shows the complete interaction flow:
StreamMessage extends Message. Key fields:
| Field | Type | Description |
|---|---|---|
content | String? | Streaming content fragment from the first packet |
type | String? | Server-defined text format description, e.g., text/plain |
complete | bool? | Whether generation is finished |
sync | bool? | Whether the client has completed a full fetch. If false, call requestStreamMessageContent. |
completeReason | int? | Business-defined completion reason code |
stopReason | int? | Server-defined stop reason. 0 means normal completion. |
Receive streaming messages
The SDK does not support sending streaming messages — they must be triggered by the server. When a streaming message arrives, the onMessageReceived callback fires. Register a MessageHandler and check the message type and sync field:
NCEngine.addMessageHandler('stream-handler', MessageHandler(
onMessageReceived: (event) {
final message = event.message;
if (message is StreamMessage) {
if (message.sync == false) {
print('Received streaming message ${message.messageId}, needs fetch');
} else {
print('Streaming message already synced');
}
}
},
onMessageMetadataUpdated: (event) {
final message = event.message;
if (message is StreamMessage) {
final summary = event.metadata?['RC_Ext_StreamMsgSummary'];
if (summary != null) {
print('Streaming summary: $summary');
}
}
},
));
Fetch streaming message content
When sync == false, the streaming content has not been fully fetched. Call requestStreamMessageContent on the StreamMessage instance to start fetching. Stream data is delivered through MessageHandler callbacks in the order init → data → complete.
Register the streaming event handlers before calling requestStreamMessageContent:
NCEngine.addMessageHandler('stream-events', MessageHandler(
onStreamMessageRequestInit: (event) {
print('Stream initialized: ${event.messageId}');
},
onStreamMessageRequestDelta: (event) {
print('Received chunk: ${event.chunkInfo?.content}');
},
onStreamMessageRequestComplete: (event) {
print('Stream complete: ${event.messageId}, error: ${event.error}');
},
));
Then call requestStreamMessageContent on the received StreamMessage:
if (message is StreamMessage && message.sync == false) {
await message.requestStreamMessageContent((error) {
if (error == null) {
print('Fetch started — streaming events incoming');
}
});
}
Get the streaming message summary
After the server completes content generation, it writes a summary through metadata. The default key is RC_Ext_StreamMsgSummary. Listen for metadata updates in the MessageHandler or read the metadata property on the message:
// Already handled in the MessageHandler above (onMessageMetadataUpdated)
// For historical messages:
if (message is StreamMessage && message.complete == true) {
final summary = message.metadata?['RC_Ext_StreamMsgSummary'];
print('Historical streaming summary: $summary');
}