嵌套的 StreamBuilder 是好的模式吗?

Posted

技术标签:

【中文标题】嵌套的 StreamBuilder 是好的模式吗?【英文标题】:Is nested StreamBuilder good pattern? 【发布时间】:2019-09-24 12:18:20 【问题描述】:

我正在使用 Bloc Pattern 和 Streams 从 HackerNews API 获取文章。

我正在加载所有文章并在流构建器的帮助下在 UI 中呈现,这很好用。

现在我用新的加载 StreamBuilder 包装了获取 Stream builder 的文章。 现在,当加载流构建器为 true(意味着它正在加载)时,它会显示一个循环进度指示器,否则,它会显示子级(使用 Stream Builder 包装的文章列表)。

这很好用。但是让我烦恼的是,我将 Stream builder 包装在一个流构建器中。我知道我可以得到 rxdart 的帮助,但我不确定如何。

我尝试在 snapshot.hasData 的帮助下添加一个加载器,但没有成功,所以我决定创建另一个流和主题,它接受一个布尔值并告诉 UI 是否正在加载。

代码在块内获取数据:

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

用户界面:

@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(),
              ),
            );
          
        ,
      ),
  .........

编辑

我已经尝试过了,但是这不起作用:

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();
          
        
      ),

【问题讨论】:

【参考方案1】:

我认为没有一种完整的方法可以避免嵌套的 StreamBuilders。我个人不会认为这是一个不好的做法,但它肯定会导致更多的构建。 在您的情况下,您可以修改 hnBloc 以发出可以是加载状态或数据状态的单个状态,从而消除对嵌套 StreamBuider 的需要。

例如。

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(),
              ),
            

          ,
)  

这种模式在使用 flutter_bloc 包时很常见。您可以查看此here 的基本示例以更好地理解它。

【讨论】:

感谢您的回复@nonybrighto,但我尝试过这种方式,但进度条没有出现。旧数据保留在屏幕上,因此不会出现圆形进度条。我已经编辑了问题以显示我做了什么。 这不是我提供的链接中使用的模式,但是如果你这样做,你必须删除你的 initialData 以便在没有数据时可以显示进度并且你还必须添加随时更新文章主题以清除旧数据。不过,我认为您不必担心嵌套的 StreamBuilder。

以上是关于嵌套的 StreamBuilder 是好的模式吗?的主要内容,如果未能解决你的问题,请参考以下文章

www 子域是好的做法吗?

什么是好的API与设计流程和设计原则

我应该在 Laravel 中嵌套资源的路由吗?

#endif GUARD_H 是好的做法吗? [复制]

Utils文件是好的做法吗? [关闭]

单行“if”/“for”语句是好的 Python 风格吗?