【问题标题】:Issue With Nested BlocBuilder() Calls嵌套 BlocBuilder() 调用的问题
【发布时间】:2021-09-15 09:26:56
【问题描述】:

我的 Flutter 应用程序有多个 BloC(通过 blocflutter_bloc 包),这导致了一些技术困难,我使用一种变通方法解决了这些问题,但我想知道是否存在是一个更好的解决方案。

我使用 BlocBuilder() 在收听一个 bloc 时,每个 bloc 都有自己的 BlocBuilder() 调用。起初,我将 BlocBuilder() 调用嵌套如下:

Widget build(BuildContext context) {
    return BlocBuilder (
           
       bloc: bloc1,
            
       builder: (ctx, snapshot1) {
          do_something1(snapshot1);
                
          return BlocBuilder(ctx2, snapshot2) {
             bloc: bloc2,
             builder: (ctx2, snapshot2) {
                       
                do_something2(snapshot2);
                      
                return renderWidget();
             }
             
          }
            
       }
       
    );
    
}

我对这个嵌套的 BlocBuilder() 调用的问题是,如果 bloc1 的数据进入,则 bloc2 的 BlocBuilder() 将被重新调用,导致 bloc2 的当前状态被 re-read() 并导致do_something2() 的困难,理想情况下,只有在 bloc2 有新数据时才应该调用它。

所以我所做的是为每个 BlocBuilder() 调用创建一个单独的小部件,从而产生以下新的 build():

Widget build(BuildContext context) {
    return Column(
         
       children: [
          WidgetBlocBuilder1(),
                
          WidgetBlocBuilder2(),
          renderWidget(),
        ],
    
    );
}

这样做的作用是,传入 bloc1 或 bloc2 的任何数据都将分别本地化到 WidgetBlocBuilder1() 或 WidgetBlocBuilder2() 中,更重要的是,传入的 bloc 数据不会导致另一个 bloc 的 BlocBuilder() 被重新-call() 就像我的嵌套 BlocBuilder() 方法一样。

这是 WidgetBlocBuilder1() 的 build():

Widget build(BuildContext context) {
    return BlocBuilder(
      bloc: bloc,
      builder: (ctx, snapshot) {
        if (snapshot is CommandEditorSaveFile) {
          _saveDocumentFile(ctx);
        }
        return Visibility(
          child: Text('test'),
          visible: false,
        );
      },
    );
}

请注意,WidgetBlocBuilder1() 是一个不可见的小部件,如 Visibility(visible:false) 包装器所示。这是因为小部件本身不应在屏幕上呈现任何内容;该小部件只是 BlocBuilder() 调用的包装器。如果传入的 bloc 数据应该改变父窗口小部件的可见状态,则需要编写逻辑来实现。

这种解决方法似乎可行,但我想知道是否有更好的解决方案。

任何建议将不胜感激。

/小何塞

【问题讨论】:

  • 你不能用一个StreamBuilder代替两个BlocBuilders吗?
  • pskink,感谢您的回复,但我宁愿保持我目前拥有的集团数量,即两个。我可以切换到流而不是块,但这仍然会给我留下 2 个要收听的流,因此需要 2 个 StreamBuilders()。如果我嵌套调用这个 StreamBuilders(),我最终会遇到与开始时相同的问题。
  • “我最终会遇到与我开始时相同的问题。” - 不,我的意思是你还有两个 Blocs,你使用一个来显示组合数据StreamBuilder
  • pskink,我不知道这是可能的。让我调查一下,然后回复你。
  • pskink,根据您的建议,我能够使用一个 StreamBuilder 收听多个区块。我使用了 multiple_streambuilder 包。谢谢。

标签: flutter bloc flutter-bloc


【解决方案1】:

根据 pskink 的建议,另一种解决方案是使用一个 StreamBuilder() 来监听多个 bloc。为此,我使用了一个名为 multiple_streambuilder 的包。

这是使用此包的示例 build():

  Widget build(BuildContext context) {
    return StreamBuilder2<int, int>(
      streams: Tuple2(bloc1!.stream, bloc2!.stream),
      builder: (contex, snapshot) {
        if (snapshot.item1.hasData) {
          print(snapshot.item1.data);
        }
        if (snapshot.item2.hasData) {
          print(snapshot.item2.data);
        }
        return Scaffold(
          appBar: AppBar(title: Text("test title")),
          body: WidgetTest(),
        );
      },
    );
 }

在上面的 build() 中,我正在监听 2 个 bloc,它们都返回一个 int,因此调用了 StreamBuilder2()。要找出哪个 bloc 发出了数据,请调用 snapshot.item1.hasdatasnapshot.item2.hasdata

【讨论】:

  • 哇,从来不知道我们可以在一个小部件中收听多个 bloc,因为我跳到 flutter_bloc 并且在了解它时从不接触流构建器,哈哈。点赞!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多