How to Use StreamBuilder in Flutter: Simple Guide
Use
StreamBuilder in Flutter to build widgets that listen to a Stream and rebuild automatically when new data arrives. Provide the stream and a builder function that returns widgets based on the stream snapshot.Syntax
The StreamBuilder widget listens to a Stream and rebuilds its child widgets when the stream emits new data. It requires two main parts:
- stream: The source of asynchronous data.
- builder: A function that takes the current snapshot of the stream and returns a widget.
dart
StreamBuilder<T>( stream: yourStream, // The stream to listen to builder: (BuildContext context, AsyncSnapshot<T> snapshot) { if (snapshot.hasData) { return Text('Data: ${snapshot.data}'); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return CircularProgressIndicator(); } }, )
Example
This example shows a StreamBuilder that listens to a stream emitting integers every second and displays the current count. It updates the UI automatically as new numbers arrive.
dart
import 'dart:async'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { final Stream<int> numberStream = Stream.periodic( Duration(seconds: 1), (count) => count, ).take(10); // Emits 0 to 9 every second @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('StreamBuilder Example')), body: Center( child: StreamBuilder<int>( stream: numberStream, builder: (context, snapshot) { if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else if (!snapshot.hasData) { return CircularProgressIndicator(); } else { return Text('Current number: ${snapshot.data}', style: TextStyle(fontSize: 24)); } }, ), ), ), ); } }
Output
A screen with an app bar titled 'StreamBuilder Example' and centered text that updates every second showing 'Current number: 0', then 1, 2, ... up to 9.
Common Pitfalls
- Not handling null or no data: Always check
snapshot.hasDatabefore usingsnapshot.datato avoid errors. - Ignoring errors: Use
snapshot.hasErrorto show error messages or fallback UI. - Recreating streams inside
build: Define streams outside thebuildmethod to avoid restarting the stream on every rebuild.
dart
/* Wrong: recreating stream inside build causes stream to restart */ StreamBuilder<int>( stream: Stream.periodic(Duration(seconds: 1), (count) => count), builder: (context, snapshot) { // ... }, ); /* Right: define stream once outside build */ final myStream = Stream.periodic(Duration(seconds: 1), (count) => count); StreamBuilder<int>( stream: myStream, builder: (context, snapshot) { // ... }, );
Quick Reference
Remember these tips when using StreamBuilder:
- Always check
snapshot.hasDatabefore accessing data. - Handle errors with
snapshot.hasError. - Provide a loading widget when no data is available yet.
- Define streams outside the
buildmethod to avoid restarting.
Key Takeaways
StreamBuilder rebuilds UI automatically when the stream emits new data.
Always check snapshot states: hasData, hasError, and connectionState.
Define streams outside the build method to prevent unwanted restarts.
Provide fallback widgets for loading and error states.
Use StreamBuilder to connect asynchronous data streams to your UI easily.