在某些情况下可以跳过BlocBuilder渲染吗?

时间:2019-05-24 03:22:47

标签: flutter loading bloc

有一个屏幕上有一个集团MyBloc myBloc

在屏幕的构建方法中,就像这样:

Widget build(BuildContext context) {
    return MyCustomLoadingStack( //My custom widget to have the main content below the loading widget
        _buildContent(context), //My main content
        _buildLoading(context)); //My loading on top
}

还有我的2种方法:

Widget _buildContent(BuildContext context) {
 return Column(children: <Widget>[
      OtherWidgetOne(),
      OtherWidgetTwo(),
      BlocBuilder<MyEvent, MyState>(
          bloc: myBloc,
          builder: (BuildContext context, MyStatestate) {
            switch (state.type) {
              case MyStateList.doneWorking:
                return MyDataWidget(); // this content cares about displaying the data only
              default:
                return Container(); //otherwise display nothing
            }
          },
        )
]);

}

Widget _buildLoading(BuildContext context) {
 return BlocBuilder<MyEvent, MyState>(
          bloc: myBloc,
          builder: (BuildContext context, MyState state) {
            switch (state.type) {
              case MyStateList.loading:
                return LoadingView(); //This _buildLoading cares the loading only
              default:
                return Container(); //If it's not loading the show nothing for the loading layer
            }
          },
        )
}

我的问题是内容当前正在显示数据。当我yield MyState(type: MyStateList.loading)进行其他操作时显示加载时(例如,为当前显示的数据加载更多)。两个BlocBuilder都被调用,然后_buildContent(context)不显示任何内容,因为它不符合MyStateList.doneWorking条件。当然,_buildLoading(context)会在下面的空白内容中显示加载情况。

无论如何,我是否可以跳过_buildContent(context)内的BlocBuilder以继续显示当前数据,并且仍然将负载放在最前面?

我虽然希望有一个小部件来包含数据,或者在Container()的默认情况下使用空的_buildContent(context),但是这对我来说没有意义,因为它们可能会重新呈现相同的内容小部件。

谢谢您的时间。

2 个答案:

答案 0 :(得分:0)

好问题!您为什么使用BlocBuilder而不是StreamBuilder是有原因的?

要在加载数据时不显示任何内容,并且在加载数据后自动填充数据,我通常会执行以下操作:

   Widget _buildLoading(BuildContext context) {
     return StreamBuilder<Model>(
              stream: bloc.modelStream,
              builder: (context, snapshot) {

    if (snapshot.hasError) return _buildErrorWidget(snapshot.error, context);

    if (snapshot.hasData) {
              return DesiredWidget()
    } else {
    return LoadingView()
    }
}

我没有看到您的BloC文件,但您可能需要添加几行,如下所示:

final _modelFetcher = BehaviorSubject<Model>();
Stream<Model> get modelStream => _modelFetcher.stream;

Function(Model) get changeModelFetcher => _modelFetcher.sink.add;


@override
  void dispose() async {
    await _modelFetcher.drain();
    _modelFetcher.close();
}

让我知道这是否有帮助。

答案 1 :(得分:0)

现在讨论了pullrequest蜜蜂来解决此问题: https://github.com/felangel/bloc/issues/315?fbclid=IwAR2x_Q1x5MIUUPE7zFRpjNkhjx5CzR0qiRx-P3IKZR_VRGEp3eqQisTthDo

现在,您可以将类用于更复杂的状态。可能是这样的:

class MyState extends Equatable {
  final bool isLoading;
  final List<MyData> data;
  bool get hasData => data.isNotEmpty;

  MyState(this.isLoading,this.data) : super([isLoading,data]);
}

我使用Equatable(https://pub.dev/packages/equatable)来简化isEqual的实现。

Widget _buildContent(BuildContext context) {
  return Column(children: <Widget>[
    OtherWidgetOne(),
    OtherWidgetTwo(),
    BlocBuilder<MyEvent, MyState>(
      bloc: myBloc,
      builder: (BuildContext context, MyStatestate) {
        if (state.hasData) {
          return MyDataWidget(); // this content cares about displaying the data only
        } else {
          return Container(); //otherwise display nothing
        }
      },
    )
  ]);
}

Widget _buildLoading(BuildContext context) {
  return BlocBuilder<MyEvent, MyState>(
    bloc: myBloc,
    builder: (BuildContext context, MyState state) {
      if (state.isLoading) {
          return LoadingView(); //This _buildLoading cares the loading only
      } else {
        return Container(); //If it's not loading the show nothing for the loading layer
      }
    },
  );
}

此方法的缺点是,即使数据没有更改,datawidget也将重绘。这将通过上述的pullrequest修复。