[Widget of the Week]: StreamBuilder
![[Widget of the Week]: StreamBuilder](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1575285308855%2FrtM8vmIUP.jpeg&w=3840&q=75)
I am a full stack developer from Lagos, Nigeria. I am passionate about web development and ecosystem. I love learning, building and exploring tools.
Search for a command to run...
![[Widget of the Week]: StreamBuilder](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1575285308855%2FrtM8vmIUP.jpeg&w=3840&q=75)
I am a full stack developer from Lagos, Nigeria. I am passionate about web development and ecosystem. I love learning, building and exploring tools.
No comments yet. Be the first to comment.
In this series, I will be posting an article about flutter widget every week, it will explain more about the week and also some use case of the widget
Picture this: You're building a Flutter app for a food delivery service. Your app needs to track user analytics, manage configuration settings, handle API calls, and maintain a logging system. Without proper architecture, you might end up creating mu...

Introduction If you've ever built a moderately complex Flutter app, you've probably hit that moment where everything starts to feel... messy. Maybe your state management is tangled, your service classes are doing too much, or you're duplicating logic...

Flutter is a cross-platform mobile framework i.e its support for Android, iOS, macOS, Window, Linux e.t.c, developing flutter is so fascinating that you get to write once and run on all platforms. in this post, I will be showing how to run more than ...

It's 2020 and the rate in which Flutter is trending is increasing exponentially, and learning can be difficult if people are not been pointed to the right resources. With the below-curated list of the youtube channel, I believe it will help flutter d...

One of the current challenges as of the time I'm writing this article is using firebase in flutter application, using firebase in your flutter application at default return error. Firebase returns different errors base on the context of what you are ...


Before I dive into StreamBuilder let me quickly digress to Stream, StreamController, they are the building blocks of Streambuilder.

Well, you are thinking, Is that stream I'm talking about! No it's not But think of it has the typical stream, A stream is an Event that's uncontrolled, that can be generated from a Future, network access, reading of files(local/network) e.t.c.which has an input(i.e where it's coming from) and output(i.e where it's going). You can also think of Stream as a pipe that has an input called the sink and output called stream. How to create a stream
Read more about Stream:https://api.flutter.dev/flutter/dart-async/Stream-class.html

the GIF image above explains a lot about StreamController, a StreamController allows you to have control over your Stream, i.e you can listen to a stream, add Stream to your StreamController, you can pause, stop your stream. if there are errors, StreamController allows you to catch those errors and handle them gracefully, StreamController gives you access to the 360-degree life cycle of a stream. StreamController API exposes some method such as: sink(which allows you to add data event) stream(the stream StreamController is controlling) map, transform (which allows you to modify or intercept your data before it emits out as a stream).
Adding Event via StreamController StreamController exposes a sink method which allows you to add item to the stream which will be emitted as a stream using stream method.
StreamController _streamController = StreamController();
//Add event/Data to the StreamController
_streamController.sink.add(data); //NB: data can be any type i.e primitive/non-primitive
//data added to the Controller via the sink is emitted as Stream via stream method.
Stream strem = _streamController.stream;
Read more about stream https://api.flutter.dev/flutter/dart-async/StreamController-class.html.
StreamBuilder is a widget that allows you to convert your stream object to a widget. rebuilding widget is basically done using setState, but performance-wise it isn't efficient because setState rebuild the whole widget and every child(s) widget, come to think of it, if you only need to rebuild a single widget then setState is a bad idea, so using StreamBuilding is your best shot. You can rebuild a single widget of your choice without touching or rebuilding the whole widget family tree.
//let assume we have a stream will want to consume
Stream stream =Stream.fromFuture(Favourite().getAllFavourite(data));
StreamBuilder(
stream: stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.data !=null){
return Widget();
}
},
);
NB: in the above snippet we try to convert our Stream to a widget, in the builder function which accepts BuildContext and AsyncSnapshot as a parameter it looks exactly like FutureBuilder if you are familiar with it. we can get access to our Stream data using snapshot.data.
if you want to check your connection state, maybe to perform a specific operation, you can do that with the below snippet;
StreamBuilder(
stream: stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.connectionState == ConnectionState.active){
// Your statement when the connection mode is in active state
}
else if(snapshot.connectionState == ConnectionState.done){
//Your statement when the operation has finished execution
}
else if (snapshot.connectionState == ConnectionState.none){
//Your statement when the connection is not available
}
else if( snapshot.connectionState == ConnectionState.waiting){
//Your statement when the connection state is in waiting mode
}
else{
// else Statement
}
},
);
below is the demo of how I used Streambuilder on flutter boilerplate counter app instead of setState.
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
StreamController _streamController ;
Stream _stream;
@override
void initState() {
_streamController = StreamController();
_stream= _streamController.stream;
}
void _incrementCounter() {
_streamController.sink.add(_counter++);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
StreamBuilder(
stream: _stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
return Text(
snapshot.data!=null ? snapshot.data.toString() : "0",
style: Theme.of(context).textTheme.display1,
);
}
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
@override
void dispose() {
}
}

you can check out the source code on Github: https://github.com/DAMMAK/flutter-counter-app-with-stream