我正在使用这样的StreamBuilder
-
StreamController streamController = StreamController.broadcast();
StreamBuilder(
stream: streamController.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return (snapshot.hasData == true) //THIS CONDITION!!!
? CircularProgressIndicator()
: myWidget();
)
我正在添加到我的流中 -
onPressed: () {
streamController.add(null);
},
我无法理解我应该检查以显示进度指示器或我的小部件的条件。由于我没有传递任何数据,我不能使用hasData
。我尝试传递虚拟数据,但hasData
永远不会变为假(即使在异步功能结束后)。我尝试使用connectionState
,但总是活跃的。我不知道为什么它没有改变到waiting
状态。当我使用FutureBuilder
时它会这样做。 (我想我可以检查一下,如果状态是waiting
,显示进度指示器,但这不起作用。为什么?)
请帮忙。
总是当我有一个异步调用返回我的Future数据时,我需要这个响应来使用我认为在BLoC模式中的流更新我的UI层。需要更多的代码,但会简化您的问题,使您的代码更具可读性,可扩展性,并保持流和异步调用从UI代码中排除其他东西。
在你的情况下它很简单:
enum DownloadState { NO_DOWNLOAD, DOWNLOADING, SUCCESS }
用于跟踪async
的状态的枚举通过示例调用网络API调用。
class Bloc {
final ApiClass api = new ApiClass(); // simulating your downloader object
final StreamController controller = StreamController<DownloadState>.broadcast();
Stream get dataState => controller.stream; // exposing your stream output
void _changeState( final DownloadState state ) => controller.sink.add( state );
void downloadData(){
_changeState( DowloadState.DOWNLOADING );
// assuming that this call returns a Future object.
api.downloadData().then( (yourNetworkData) {
// handle your downloaded data
_changeState( DownloadState.SUCCESS );
} ).catchError( (apiError) => controller.sink.addError( apiError ); );
}
}
一个暴露流的BLoC类,在这个类中,我们创建了通过示例调用网络API的方法,当获取结果时,我们可以保存值,转换这些值,使用流和其他东西发送到UI。在Future对象完成之后的downloadData
中,我们只是将DownloadState
值放入流中,这将强制使用StreamBuilder
帮助在UI层中重建正在侦听controller.stream的小部件。如果我们从网络调用中得到一些错误,我们把它放在流错误输出controller.sink.addError
中,在UI层我们可以用snapshot.hasError
属性检查这个。
在你的UI层......
Bloc bloc = Bloc(); // you can create a instance of BLoC in initState or in widget contructor...
StreamBuilder<DownloadState>(
stream: bloc.dataState, // bloc get method that returns stream output.
initialData: DownloadState.NO_DOWNLOAD. // this will be the inital value. It's optional
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData){
switch(snapshot.data){
case DownloadState.NO_DOWNLOAD:
return NoDownloadWidget();
case DownloadState.DOWNLOADING:
return CircularProgressIndicator();
case DownloadState.SUCCESS:
return myWidget();
}
}
return ErrorWidget( snapshot.error );
)
并在onPress活动中
onPressed: () => bloc.downloadData();
使用这种方法,您可以删除UI层流对象和控制器,不需要setState调用,您将拥有一个包含业务逻辑和外部api调用的特定文件,这可以使我们拥有Futures和Streams的工作变得更加轻松一起工作。
我希望它有所帮助。