【问题标题】:StreamBuilder is rebuild with previous snapshot.data and not the initialDataStreamBuilder 是用以前的 snapshot.data 而不是 initialData 重建的
【发布时间】:2021-03-16 15:37:18
【问题描述】:

我正在尝试在 Flutter 应用程序中使用 bloc 架构,为此我使用了 StreamController 和 StreamBuilder。问题是,StreamBuilder 每次返回时都会重复最后一个 snapshot.data。我正在嵌套 StreamBuilders。所以有一个主要的 StreamBuilder。它的流在 mainBloc 文件中定义。 InitialData 为 SomeEvent 并返回 someView。

SomeView 是另一个带有相应块和流的 StreamBuilder。初始数据是初始事件。在按下按钮时,SecondEvent 被添加到块接收器,因此小部件发生变化。在新视图中有另一个按钮,点击它时 mainBloc 应该再次显示相同的 SomeView。

问题就在这里。 SomeView StreamBuilder 接收到的snapshot.data 与上一个相同,但最后一个没有再次添加到sink。所以我不明白 - 这是 StreamBuilder 应该如何工作的吗?我想要实现的是 snapshot.data 有 InitialEvent 。这可能吗?或者至少不要在不触发的情况下重复 snapshot.data。

下面的代码演示了整个问题。

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  MainBloc mainBloc;
  Bloc bloc;

  MyApp() {
    mainBloc = MainBloc();
    bloc = Bloc();
  }

  Widget mainView() {
    return StreamBuilder<MainEvent>(
      stream: mainBloc.mainStream,
      initialData: SomeEvent(),
      builder: (
        context,
        snapshot,
      ) {
        if (snapshot.hasData) {
          MainEvent event = snapshot.data;
          if (event is SomeEvent) {
            return someView();
          }
          if (event is SomeEventTwo) {
            return someView();
          }
        } else {
          return Container(height: 0, width: 0);
        }
      },
    );
  }

  Widget someView() {
    return StreamBuilder<Event>(
      stream: bloc.stream,
      initialData: InitialEvent(),
      builder: (
        context,
        snapshot,
      ) {
        if (snapshot.hasData) {
          Event event = snapshot.data;
          if (event is InitialEvent) {
            return Column(
              children: [
                Center(
                  child: Text("Initial event"),
                ),
                FlatButton(
                  onPressed: () {
                    bloc.secondEvent();
                  },
                  child: Text("Trigger Second event"),
                  color: Colors.pink,
                ),
              ],
            );
          }
          if (event is SecondEvent) {
            return Center(
              child: FlatButton(
                child: Text("Show same screen again"),
                onPressed: () {
                  bloc.dispose();
                  bloc = Bloc();
                  mainBloc.showScreenTwo();
                },
                color: Colors.blue,
              ),
            );
          }
        } else {
          return Container(height: 0, width: 0);
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.grey,
        ),
        body: mainView(),
      ),
    );
  }
}

这些是集团: 主块:

class MainBloc {
  StreamController<MainEvent> _mainStreamController;

  StreamSink<MainEvent> get _mainSink => _mainStreamController.sink;

  Stream<MainEvent> get mainStream => _mainStreamController.stream;

  MainBloc() {
    _mainStreamController = StreamController<MainEvent>();
  }

  void showScreen() {
    _mainSink.add(SomeEvent());
  }

  void showScreenTwo() {
    _mainSink.add(SomeEventTwo());
  }
}

abstract class MainEvent {}

class SomeEvent extends MainEvent {}

class SomeEventTwo extends MainEvent {}

集团:

class Bloc {
  StreamController<Event> _controller;

  StreamSink<Event> get _sink => _controller.sink;

  Stream<Event> get stream => _controller.stream;

  Bloc() {
    _controller = StreamController<Event>();
  }

  void secondEvent() async {
    _sink.add(SecondEvent());
  }

  dispose() {
    _controller.close();
  }
}

abstract class Event {}

class InitialEvent extends Event {}

class SecondEvent extends Event {}

【问题讨论】:

    标签: flutter bloc stream-builder


    【解决方案1】:

    尚未对其进行测试,但也许可以在您的MaterialApp之外尝试

    class MainView extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return StreamBuilder<MainEvent>(
          stream: mainBloc.mainStream,
          initialData: SomeEvent(),
          builder: (
            context,
            snapshot,
          ) {
            if (snapshot.hasData) {
              MainEvent event = snapshot.data;
              if (event is SomeEvent) {
                return someView();
              }
              if (event is SomeEventTwo) {
                return someView();
              }
            } else {
              return Container(height: 0, width: 0);
            }
          },
        );
      }
    }
    

    而不是Widget someView(){ return ... }

    如果您使用自己的构建方法而不是 StatelessWidget 声明,setState 行为有时会有所不同。

    【讨论】:

      猜你喜欢
      • 2020-07-11
      • 2020-09-19
      • 2021-06-24
      • 2021-06-27
      • 2019-05-31
      • 2021-09-29
      • 2019-03-26
      • 2019-12-31
      • 1970-01-01
      相关资源
      最近更新 更多