Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is nested StreamBuilder good pattern?

I am fetching articles from HackerNews API using Bloc Pattern and Streams.

I am loading all the articles and presenting in the UI with the help of a stream builder, and this works fine.

Now I wrapped the article fetching Stream builder with the new loading StreamBuilder. Now when the loading stream builder has true (means it is loading) it shows a circular progress indicator or else, it shows the child (Article List wrapped with a Stream Builder).

This works fine. But it is bugging me that I have wrapped Stream builder inside a stream builder. I know I can take help of rxdart but I am just not sure how.

I tried to add a loader with the help of snapshot.hasData or not but that didn't work, so I decided to create another stream and subject that takes a bool and tells the UI if it is loading or not.

Code fetching data int the bloc:

 _getAndUpdateArticles(StoryType storyType) {
    _isLoadingSubject.add(true);
    getListIds(storyType).then((list) {
      getArticles(list.sublist(0, 10)).then((_){
        _articleSubject.add(UnmodifiableListView(_articles));
        _isLoadingSubject.add(false);
      });
    });
  }

UI:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: StreamBuilder(
        stream: widget.hnBloc.isLoading,
        builder: (context, snapshot) {
          if (snapshot.data) {
            return Center(child: CircularProgressIndicator());
          } else {
            return StreamBuilder<UnmodifiableListView<Article>> (
              initialData: UnmodifiableListView<Article>([]),
              stream: widget.hnBloc.article,
              builder: (context, snapshot) => ListView(
                children: snapshot.data.map(_buildItem).toList(),
              ),
            );
          }
        },
      ),
  .........

EDIT

I have tried this, but this isn't working:

StreamBuilder<UnmodifiableListView<Article>> (
        initialData: UnmodifiableListView<Article>([]),
        stream: widget.hnBloc.article,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView(
              children: snapshot.data.map(_buildItem).toList(),
            );
          } else {
            return CircularProgressIndicator();
          }
        }
      ),
like image 789
Dhruvam Sharma Avatar asked May 06 '19 20:05

Dhruvam Sharma


People also ask

What is the use of StreamBuilder?

The StreamBuilder can listen to exposed streams and return widgets and catch snapshots of got stream information. The stream builder takes two contentions. The Stream resembles a line. At the point when you enter a value from one side and a listener from the opposite side, the listener will get that value.

What is StreamBuilder stream?

A stream builder is a widget that can convert user-defined objects into a stream.

How do you make StreamBuilder in flutter?

To use StreamBuilder , you need to call the constructor below. Basically, you need to create a Stream and pass it as the stream argument. Then, you have to pass an AsyncWidgetBuilder which can be used to build the widget based on the snapshots of the Stream .


1 Answers

I Don't think there is a complete way to avoid nested StreamBuilders. I personally wouldn't consider it a bad practice, but it will definitely lead to more build.
In your case, You can modify your hnBloc to emit a single state that can be a loading state or data state , thereby eliminating the need for a nested StreamBuider.

eg.

StreamBuilder<HnState>(
          stream: hnBloc.currentState,
          initialData: HnLoadingState(),
          builder: (context, snapshot) {
            if (snapshot.data is HnLoadingState) {
              return Center(child: CircularProgressIndicator());
            }if (snapshot.data is HnDataState) {
              return ListView(
                children: snapshot.data.map(_buildItem).toList(),
              ),
            }

          },
)  

This pattern is very common when using the flutter_bloc package. You can see a basic example of this here to understand it better.

like image 163
nonybrighto Avatar answered Oct 23 '22 16:10

nonybrighto