Flutter StreamBuilder: An Ultimate Guide

flutter streambuilder firestore

Flutter StreamBuilder is a widget that allows you to display real-time data within the apps. The most use case scenario of StreamBuilder could be in chatting apps or real-time stock trading apps.  

When the asynchronous process is active, you can make a capacity that returns a stream that emanates a few values. Let’s say you must construct a widget that works on the snapshots of the stream and is Flutter-dependent. Then you use a widget called the StreamBuilder. 

In this blog, we will be discussing Flutter SteamBuilder in detail and building a demo app using Firebase Cloud Firestore to show you how it StreamBuilder actually works.  Let’s jump right into it. 😉

What is Flutter StreamBuilder? 

It’s a widget that listens to the events that come from the Streams and rebuilds itself for upcoming events.

You need to provide the Streambuilder with a stream and initial data. It’s because the widget has something to show while waiting for the upcoming event.  This strategy is helpful when the widget is network-dependent.

Moreover, it has a snapshot to keep track of the multiple states like having data in it or not during active connection. 

The stream builder has two parts, the stream, and the builder. The stream builder can change over user-defined objects into a stream.

How does it work?

The stream resembles a line and you need to enter a value at some point from one side. On the opposite side, you will enter the listener, the listener receives that value. 

A stream can have multiple listeners getting the pipeline having the equivalent value. The Stream Controller utilizes how you put values on the stream. 

Let’s build a demo app and show you how Flutter StreamBuilder works. 

Code:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class StreamBuilderExample extends StatefulWidget {
  const StreamBuilderExample({Key? key}) : super(key: key);

  @override
  State<StreamBuilderExample> createState() => _StreamBuilderExampleState();
}

class _StreamBuilderExampleState extends State<StreamBuilderExample> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        elevation: 0,
        title: const Text('StreamBuilder Example'),
      ),
      body: StreamBuilder<List<FirebaseDataModel>>(
        stream: FireStoreService().fetchAllSortedFirestore(),
        builder: (_, AsyncSnapshot<List<FirebaseDataModel>> snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return const Center(
              child: Text(
                'Something went wrong',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.w500,
                ),
              ),
            );
          } else {
            if (snapshot.data?.isEmpty ?? true) {
              return const Center(
                child: Text(
                  'No records available',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              );
            } else {
              final data = snapshot.data;
              return ListView.builder(
                itemBuilder: (_, i) {
                  final student = data?[i];
                  return ListTile(
                    title: Text(student?.name ?? ''),
                    subtitle: Text(student?.fatherName ?? ''),
                  );
                },
                itemCount: data?.length,
              );
            }
          }
        },
      ),
    );
  }
}

class FireStoreService {
  Stream<List<FirebaseDataModel>> fetchAllSortedFirestore() =>
      FirebaseFirestore.instance.collection('students').snapshots().map((s) =>
          s.docs.map((doc) => FirebaseDataModel.fromJson(doc.data())).toList());
}

/// Coming data is structured according to this model
class FirebaseDataModel {
  final String name;
  final String fatherName;

  FirebaseDataModel({required this.name, required this.fatherName});

  factory FirebaseDataModel.fromJson(Map<String, dynamic> json) =>
      FirebaseDataModel(
        name: json['name'],
        fatherName: json['fatherName'],
      );
}

Output

Let us get to know the components and functions that are used in StreamBuilder.

Constructor:

You must have the constructor to use the StreamBuilder widget. 

Making a Stream and passing it as the stream contention is what you need to do. We then pass the AsyncWidgetBuilder to generate the widget based on the snapshots of the Stream.

Parameters:

Some key parameters of StreamBuilder are the following; 

Key? (key): 

It controls how one widget replaces the other widget.

Stream<T>? (stream):

The stream has to be there whose snapshot is taken by the builder function in Flutter.

T? initial data: 

We use this data at the point of taking an initial snapshot.

AsyncWidgetBuilder<T> builder: 

Further, the AsynchWidgetBuilder utilizes the procedure of the Builder. This is because the StreamBuilder processes again and again as we change the input.

Using The Flutter StreamBuilder and Implementing  The Code In Dart File:

You need to go through all the following steps to use the Flutter StreamBuilder.

Creating a Stream:

You must have a function to produce a Stream for generating numbers once every second. To create a Stream, you must use the async* keyword. You can also use the yield keyword followed by the value to be emitted as emit.

Creating an AsyncWidgetBuilder

The identified contention builder must be of type AsyncWidgetBuilder and be passed to the function Object() { [native code] }. It is a function with two inputs of the types BuildContext and AsyncSnapshotT> combined.

Learn about AsyncSnapshot, which provides a static representation of the most recent interaction with an asynchronous computation. It speaks to the most recent exchange with a stream here. To obtain the most recent snapshot of the Stream, access the AsyncSnapshot attributes

Passing The Initial Data:

Additionally, AsyncSnapshot offers a property called hasError that may be used to determine whether the snapshot has any non-null error values.

The initial data value will be used up until the stream emits an emission. In any case, the property will initially be true when the connection state waiting if the provided value is not null.

Final Words

The Flutter StreamBuilder can help you create a flutter widget that depends on snapshots of the screen. We have given you basic knowledge about this widget and provided you with the sample code. It’s completely royalty-free, you can use and change the code according to your desire.

We hope to have provided you with sufficient knowledge about Flutter StreamBuilder in this article. We continue to bring such information to the table. Stay in touch with us and we will keep bringing you useful pieces of information every next day. See you in the next blog. 👋 👋

Leave a Comment

Your email address will not be published. Required fields are marked *

Share Post On

Haroon Ashraf

Flutter Developer

Detail-oriented full-stack engineer with 9+ years of industry experience. He’s been working on Flutter since 2018 and has delivered 30+ successful projects.He has experience in project management Trello, Github, Jira…..

Flutter
Xcode
IOS-Swift
Full Stack
Bloc/Cubit
Nodejs

Experience

Availability

9 years

Full-Time

Translate »