Middle
How are streams used in Flutter?
sobes.tech AI
Answer from AI
Streams in Flutter are used for handling sequences of asynchronous events. These can include data from the network, user input, state changes, etc.
Key aspects of usage:
- Asynchronous programming: Streams are based on
Future, but represent a stream of events rather than a single future value. - UI updates: Streams are often used to update the user interface in response to data changes without blocking the main thread.
- Reactive programming: They form the basis for reactive approaches in state management (e.g., using BLoC or Provider with
StreamProvider).
Main classes:
Stream: Represents a sequence of asynchronous events. You cannot create aStreamdirectly; it is created by a data source (e.g.,HttpClient,File.watch,StreamController).StreamController: Allows creating and managing streams. Used to add data or errors to the stream.StreamSubscription: An object returned when subscribing to a stream. It allows listening to events and canceling the subscription.
// Creating a stream via StreamController
final _controller = StreamController<int>();
// Adding data to the stream
void addData(int data) {
_controller.sink.add(data);
}
// Getting the stream for listening
Stream<int> get stream => _controller.stream;
// Closing the controller when no longer needed
void dispose() {
_controller.close();
}
Usage examples:
- Handling button press events:
StreamController<void> _buttonClicked = StreamController(); - Receiving data from WebSocket:
_socket.listen((data) => _streamController.add(data)); - Implementing timers:
Stream<int> countStream = Stream.periodic(Duration(seconds: 1), (count) => count);
Widget integration:
StreamBuilder: A widget that rebuilds its subtree every time the stream emits a new value.
StreamBuilder<int>(
stream: countStream, // The same stream from the example above
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Select a number');
case ConnectionState.waiting:
return Text('Waiting...');
case ConnectionState.active:
return Text('${snapshot.data}'); // Displaying the current stream value
case ConnectionState.done:
return Text('${snapshot.data} (Closed)');
}
},
)
Advantages:
- Simplify asynchronous data processing.
- Enable creating responsive user interfaces.
- Are a key element of architectural patterns like BLoC.
It is important to manage the lifecycle of subscriptions (StreamSubscription.cancel()) and controllers (StreamController.close()) to prevent memory leaks.