BLoC和多个流-是否有更好的解决方案?

时间:2019-07-12 12:13:05

标签: flutter bloc

目前,我正在Flutter中使用BLoC,我对一个Bloc中的多个流有疑问。

例如,当屏幕上有多个取决于Bloc的小部件时。我可以将整个屏幕包装在StreamBuilder中,但是每次都将重新构建所有小部件时。

示例集团:

class TestBloc {
  final StreamController _dataController = StreamController<String>();
  final StreamController _appBarTitleController = StreamController<String>();

  TestBloc();

  Stream<String> get appBarTitle => _appBarTitleController.stream;

  Stream<DataState> get data => _dataController.stream;

  void fetchData(String path) async {
    _dataController.sink.add(PokemonDataLoading());

    Data data = await _getData();

    _dataController.sink.add(Loaded(data));
    _appBarTitleController.sink.add(data.name);
  }

  Future<Data> _getData(String path) async {
    return await _dataRepository.fetchData(path);
  }

  void dispose() {
    _dataController.close();
    _appBarTitleController.close();
  }
}

在示例构建方法上,您可以看到两种不同的StreamBuilder,一种用于应用栏标题,另一种用于内容。当然,我可以在此示例中将它们包装到一个StreamBuilder中,但是有时这并非易事。它们可能取决于其他数据或用户交互。

@override
Widget build(BuildContext context) {
  _testBloc.fetchData();

  return ScaffoldWithSafeArea(
    title: StreamBuilder(
      stream: _testBloc.appBarTitle,
      builder: (context, AsyncSnapshot<String> snapshot) {
        if (snapshot.hasData) {
          return Text(snapshot.data);
        }
        return Text("Test");
      },
    ),
    child: StreamBuilder<DataState>(
      stream: _testBloc.data,
      builder: (context, AsyncSnapshot<DataState> snapshot) {
        DataState state = snapshot.data;

        if (state is DataInitial) {
          return _buildLoading();
        } else if (state is DataLoaded) {
          return _buildContent(state.data);
        }
        return _buildLoading();
      },
    ),
  );
}

对于一个屏幕上的多个流,是否有更好的解决方案?我在这里使用了很多样板代码,并希望避免这种情况。

1 个答案:

答案 0 :(得分:1)

要在一个屏幕上管理多个流,最好的解决方案是让多个小部件监听相应的流。

通过这种方式,您可以通过优化小部件的构建总数来提高应用程序的性能。

这样做,您可以创建小部件,以监听BLoC的输出(流),并在应用程序的不同部分中重复使用它们,但是要使小部件可重用,您需要在该小部件中注入块。

如果看到BLoC UI design guidelines

  

每个“足够复杂”的组件都有一个对应的BLoC

这样,您的屏幕现在将由不同的组件组成,并且该组件是一个小部件,用于监听BLoC的输出(流)。

所以你做得对。

如果您想减少小部件中的重复代码,可以:

  • 创建自己的小部件,以侦听流并直接返回BLoC的输出(在您的情况下,您称为状态),这样,您就无需像{ {1}}。此小部件的示例是BlocBuilder库中的flutter bloc

  • 使用flutter bloc库,该库具有在使用BLoC模式时减少样板代码的小部件,但是,如果使用此库,则现在需要使用bloc库来创建BLoC,但如果这样做之后,现在您可以减少BLoC中创建snapshot.data的样板代码以及其他有趣的功能,因此您应该看看bloc和flutter bloc库的功能。