Stream Controller
A Stream Controller is a special variable type used to push and listen to data over time. It enables reactive programming patterns where widgets automatically update in response to data changes, making it perfect for real-time updates, notifications, or any scenario where data arrives asynchronously.
Supported Widgets
The Stream Controller can be used with:
When to Use
Use a Stream Controller when you need to:
Handle real-time data updates (chat messages, notifications)
Emit values over time from actions or events
Create reactive UI that responds to data streams
Implement event-driven architectures
Push multiple values to the same widget over time
Broadcast data to multiple listeners
Creating a Stream Controller
Navigate to Variables in your project
Click Add Variable
Select Stream Controller as the type
Give it a descriptive name (e.g.,
messageStream,notificationStream)
Binding to Widgets
Stream Builder Example
Stream Builder:
Stream: ${messageStream}
Builder:
Text: ${streamData.message}
Text: ${concat("Received at: ", streamData.timestamp)}The Stream Builder widget will automatically rebuild whenever new data is emitted to the stream.
Controller Methods
Use the Control Object action to invoke these methods on the controller.
add
addEmits a value to the stream, triggering all listeners to update.
value
Any
Any JSON-compatible value to emit
Example Use Cases:
Emit new message:
value: {"message": "Hello", "timestamp": "10:30 AM"}Emit notification:
value: {"type": "info", "text": "Update available"}Emit simple value:
value: 42Emit string:
value: "Status changed"
When to Use:
When new data arrives from an API or event
Responding to user actions
Broadcasting updates to UI
close
closeCloses the stream, preventing further emissions.
No parameters required.
When to Use:
Cleanup when leaving a page
Stopping real-time updates
Resource management
Important: Once a stream is closed, you cannot emit more values to it. You'll need to create a new Stream Controller if you want to continue streaming data.
Common Use Cases
1. Real-Time Chat Messages
Display incoming chat messages as they arrive.
Setup:
Variable: chatStream (Stream Controller)
Stream Builder:
Stream: ${chatStream}
Builder:
Container (Message Bubble):
Text: ${streamData.sender}
Text: ${streamData.message}
Text: ${streamData.timestamp}Implementation:
On WebSocket Message Received:
Control Object:
Object: ${chatStream}
Method: add
Arguments:
value: {
"sender": ${message.sender},
"message": ${message.text},
"timestamp": ${message.time}
}2. Live Notifications
Show real-time notifications to users.
Setup:
Variable: notificationStream (Stream Controller)
Stream Builder:
Stream: ${notificationStream}
Builder:
Container (Notification Banner):
Background: ${if(isEqual(streamData.type, 'error'), 'red', 'blue')}
Text: ${streamData.title}
Text: ${streamData.message}Implementation:
On API Response:
Control Object:
Object: ${notificationStream}
Method: add
Arguments:
value: {
"type": "success",
"title": "Success!",
"message": "Data saved successfully"
}3. Progress Updates
Stream progress updates for long-running tasks.
Setup:
Variable: progressStream (Stream Controller)
Stream Builder:
Stream: ${progressStream}
Builder:
Linear Progress Bar:
Value: ${streamData.percent}
Text: ${streamData.status}Implementation:
On Upload Progress:
Control Object:
Object: ${progressStream}
Method: add
Arguments:
value: {
"percent": ${uploadPercent},
"status": ${concat("Uploading: ", uploadPercent, "%")}
}4. Live Search Results
Stream search results as user types.
Setup:
Variable: searchResultsStream (Stream Controller)
Text Form Field:
On Change:
API Call: searchAPI
On Success:
Control Object:
Object: ${searchResultsStream}
Method: add
Arguments:
value: ${apiResponse.data.results}
Stream Builder:
Stream: ${searchResultsStream}
Builder:
ListView:
Data Source: ${streamData}5. Event Broadcasting
Emit events from one part of the app and listen elsewhere.
Setup:
Variable: appEventStream (Stream Controller)
// Emit event
On Button Click:
Control Object:
Object: ${appEventStream}
Method: add
Arguments:
value: {
"event": "user_logged_in",
"userId": ${currentUser.id}
}
// Listen to events
Stream Builder:
Stream: ${appEventStream}
Builder:
Conditional Builder:
Condition: ${isEqual(streamData.event, 'user_logged_in')}
True:
Text: ${concat("Welcome, User ", streamData.userId)}6. Cleanup on Page Exit
Close stream when leaving a page to prevent memory leaks.
On Page Dispose:
Control Object:
Object: ${messageStream}
Method: closeBest Practices
One stream per data type: Create separate streams for different types of data (messages, notifications, etc.)
Use descriptive names: Name streams after their purpose (
chatStream,notificationStream)Close streams when done: Always close streams when they're no longer needed to free resources
Emit structured data: Use JSON objects with consistent structure for easier handling
Handle initial state: Stream Builder should handle the case where no data has been emitted yet
Don't emit too frequently: Avoid emitting hundreds of times per second; consider throttling or debouncing
Validate data before emitting: Ensure data is valid and in the expected format before calling
add
Common Patterns
Emit Simple Value
Control Object:
Object: ${stream}
Method: add
Arguments:
value: "Hello World"Emit Complex Object
Control Object:
Object: ${stream}
Method: add
Arguments:
value: {
"id": 123,
"title": "New Item",
"timestamp": ${currentTimestamp}
}Close Stream on Exit
On Page Dispose:
Control Object:
Object: ${stream}
Method: closeConditional Emission
If ${shouldNotify}:
Control Object:
Object: ${notificationStream}
Method: add
Arguments:
value: ${notificationData}Stream from API Response
On API Success:
Control Object:
Object: ${dataStream}
Method: add
Arguments:
value: ${apiResponse.data}Stream Builder Integration
The Stream Builder widget is designed to work with Stream Controllers:
Stream Builder:
Stream: ${streamController}
Builder:
// Access emitted data via ${streamData}
Text: ${streamData.property}Whenever you call add() on the Stream Controller, the Stream Builder automatically rebuilds with the new streamData.
Troubleshooting
Stream Not Updating
Ensure the Stream Controller is properly bound to Stream Builder using
${streamName}Check that
addis being called with valid dataVerify the stream hasn't been closed
Stream Builder Not Rebuilding
Confirm the stream property is set correctly in Stream Builder
Check that data is being emitted (use console/debug to verify)
Ensure the value being emitted is JSON-compatible
Memory Leaks
Always close streams when leaving pages
Don't create new Stream Controllers repeatedly without closing old ones
Use
close()in page disposal lifecycle
Related Documentation
Stream Builder - Widget that listens to streams
Control Object Action - Invoke controller methods
Variables Overview - Learn about all variable types
Last updated