有一个屏幕上有一个集团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)
,但是这对我来说没有意义,因为它们可能会重新呈现相同的内容小部件。
谢谢您的时间。
答案 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修复。