Flutter StreamBuilder Widget (original) (raw)
Last Updated : 23 Jul, 2025
A **StreamBuilder in Flutter is used to listen to a stream of data and **rebuild its widget subtree whenever new data is emitted by the stream. It's commonly used for real-time updates, such as when working with streams of data from network requests, databases, or other asynchronous sources. In this article, we are going to see an example of a Streambuilder Widget by taking an Example.
**Syntax of StreamBuilder
StreamBuilder(
stream: yourStream, // The stream to listen to
initialData: initialData, // Optional initial data while waiting for the first event
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return YourLoadingWidget(); // Display a loading indicator while waiting for data
} else if (snapshot.hasError) {
return YourErrorWidget(error: snapshot.error); // Handle errors
} else if (!snapshot.hasData) {
return YourNoDataWidget(); // Handle the case when there's no data
} else {
return YourDataWidget(data: snapshot.data); // Display your UI with the data
}
},
)
Here we are going to see a simple example of a StreamBuilder in Flutter that listens to a stream of numbers and displays the latest number in real-time:
**Required Tools
- To build this app, you need the following items installed on your machine:
- Visual Studio Code / Android Studio
- Android Emulator / iOS Simulator / Physical Device device.
- Flutter Installed
- Flutter plugin for VS Code / Android Studio.
A sample video is given below to get an idea about what we are going to do in this article.
Step By Step Implementations
Step 1: Create a New Project in Android Studio
To set up Flutter Development on Android Studio please refer to **Android Studio Setup for Flutter Development, and then create a new project in Android Studio please refer to **Creating a Simple Application in Flutter.
Step 2: Import the Package
First of all import material.dart file.
import 'dart:async';
import 'package:flutter/material.dart';
Step 3: Execute the main Method
Here the execution of our app starts.
Dart `
void main() { runApp(MyApp()); }
`
Step 4: Create MyApp Class
In this class we are going to implement the MaterialApp , here we are also set the Theme of our App.
Dart `
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.green, // Set the app's primary theme color ), title: 'StreamBuilder Example', home: NumberStreamPage(), ); } }
`
Step 5: Create NumberStreamPage Class
In this class we are going to Implement the StreamBuilder to display the numbers changes in real time.Here we are going to run a for loop from 0 to 9 and display the updates number by the help of StreamBuilder.Comments are added for better understanding.
StreamBuilder(
stream: _numberStreamController.stream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(); // Display a loading indicator when waiting for data.
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}'); // Display an error message if an error occurs.
} else if (!snapshot.hasData) {
return Text('No data available'); // Display a message when no data is available.
} else {
return Text(
'Latest Number: ${snapshot.data}',
style: TextStyle(fontSize: 24),
); // Display the latest number when data is available.
}
},
),
Dart `
class _NumberStreamPageState extends State { late StreamController _numberStreamController;
@override void initState() { super.initState();
// Create a stream controller and add numbers to the stream.
_numberStreamController = StreamController<int>();
_startAddingNumbers(); // Start adding numbers to the stream.}
void _startAddingNumbers() async { for (int i = 0; i < 10; i++) { await Future.delayed(Duration(seconds: 2)); // Delay for 2 seconds. _numberStreamController.sink.add(i); // Add the number to the stream. } }
@override void dispose() { _numberStreamController.close(); // Close the stream when disposing. super.dispose(); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('StreamBuilder Example'), ), body: Center( child: StreamBuilder( stream: _numberStreamController.stream, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); // Display a loading indicator when waiting for data. } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); // Display an error message if an error occurs. } else if (!snapshot.hasData) { return Text('No data available'); // Display a message when no data is available. } else { return Text( 'Latest Number: ${snapshot.data}', style: TextStyle(fontSize: 24), ); // Display the latest number when data is available. } }, ), ), ); } }
`
**Here is the full Code of main.dart file
Dart `
import 'dart:async'; import 'package:flutter/material.dart';
void main() { runApp(MyApp()); }
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, // Remove the debug banner theme: ThemeData( primarySwatch: Colors.green, // Set the app's primary theme color to green ), title: 'StreamBuilder Example', home: NumberStreamPage(), ); } }
class NumberStreamPage extends StatefulWidget { @override _NumberStreamPageState createState() => _NumberStreamPageState(); }
class _NumberStreamPageState extends State { late StreamController _numberStreamController;
@override void initState() { super.initState();
// Create a stream controller and add numbers to the stream.
_numberStreamController = StreamController<int>();
_startAddingNumbers(); // Start adding numbers to the stream.}
void _startAddingNumbers() async { for (int i = 0; i < 10; i++) { await Future.delayed(Duration(seconds: 2)); // Delay for 2 seconds. _numberStreamController.sink.add(i); // Add the number to the stream. } }
@override void dispose() { _numberStreamController.close(); // Close the stream when disposing. super.dispose(); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('StreamBuilder Example'), ), body: Center( child: StreamBuilder( stream: _numberStreamController.stream, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); // Display a loading indicator when waiting for data. } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); // Display an error message if an error occurs. } else if (!snapshot.hasData) { return Text('No data available'); // Display a message when no data is available. } else { return Text( 'Latest Number: ${snapshot.data}', style: TextStyle(fontSize: 24), ); // Display the latest number when data is available. } }, ), ), ); } }
`