Проблема с вложенными вызовами BlocBuilder ()

В моем приложении Flutter есть несколько блоков BloC (через пакеты bloc и flutter_bloc), что вызвало некоторые технические трудности, которые я решил с помощью обходного пути, но мне было интересно, есть ли лучший решение там.

Я использую BlocBuilder () при прослушивании блока, где каждый блок имеет свой собственный вызов 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, BlocBuilder () для bloc2 будет повторно вызван, в результате чего текущее состояние для bloc2 будет повторно прочитано () и возникнут трудности для do_something2. (), который в идеале должен вызываться только при наличии новых данных для bloc2.

Итак, я создал отдельный виджет для каждого вызова BlocBuilder (), в результате получился следующий новый build ():

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

Это означает, что любые данные, поступающие для bloc1 или bloc2, будут локализованы в WidgetBlocBuilder1 () или WidgetBlocBuilder2 () соответственно и, что более важно, входящие данные блока НЕ ​​будут вызывать повторный вызов BlocBuilder () для другого блока ( ), как это было в моем вложенном подходе BlocBuilder ().

Вот build () для WidgetBlocBuilder1 ():

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 (). Если входящие данные блока должны изменить видимое состояние родительского виджета, тогда необходимо написать логику для реализации этого.

Этот обходной путь, кажется, работает, но мне было интересно, есть ли лучшее решение.

Любые предложения будут ценны.

/ Joselito


person Jose    schedule 04.07.2021    source источник
comment
нельзя ли использовать один StreamBuilder вместо двух BlocBuilder?   -  person pskink    schedule 04.07.2021
comment
pskink, спасибо за ответ, но я предпочитаю придерживаться того количества блоков, которое у меня сейчас есть, а это два. Я мог бы переключиться на потоки вместо блоков, но это все равно оставило бы мне 2 потока для прослушивания и, следовательно, потребовало бы 2 StreamBuilders (). Если я вложу вызов этого StreamBuilders (), я столкнусь с той же проблемой, с которой начал.   -  person Jose    schedule 04.07.2021
comment
Я бы столкнулся с той же проблемой, с которой начал. - нет, я имел в виду, что у вас все еще есть два Bloc, и вы показываете объединенные данные, используя один StreamBuilder   -  person pskink    schedule 04.07.2021
comment
пскинк, я не знал, что это возможно. Позвольте мне разобраться в этом и вернуться к вам.   -  person Jose    schedule 04.07.2021
comment
pskink, я смог прослушать несколько блоков с помощью одного StreamBuilder в соответствии с вашим предложением. Я использовал пакет multiple_streambuilder. Спасибо.   -  person Jose    schedule 05.07.2021


Ответы (1)


Согласно предложению pskink, другое решение - использовать один StreamBuilder () для прослушивания нескольких блоков. Для этого я использовал пакет под названием 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 блока, оба возвращали int, отсюда и вызов StreamBuilder2 ‹int, int› (). Чтобы узнать, какой блок отправил данные, вы вызываете snapshot.item1.hasdata или snapshot.item2.hasdata.

person Jose    schedule 05.07.2021
comment
Ух ты, никогда не знаешь, что мы можем прослушивать несколько блоков в одном виджете, так как я перехожу к flutter_bloc и никогда не касаюсь конструктора потоков, когда узнаю об этом lol. Проголосовали !. - person Afandi Yusuf; 05.07.2021