在streambuilder中如何检测异步操作?

问题描述 投票:0回答:1

我正在使用这样的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,显示进度指示器,但这不起作用。为什么?)

请帮忙。

asynchronous dart flutter stream
1个回答
1
投票

总是当我有一个异步调用返回我的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的工作变得更加轻松一起工作。

我希望它有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.