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

时间:2019-04-25 11:06:07

标签: asynchronous dart flutter stream

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

请帮助。

1 个答案:

答案 0 :(得分:1)

当我有一个异步调用返回我未来的数据时,也需要此响应来使用我认为是BLoC模式的流更新我的UI层。需要更多的代码,但是它将简化您的问题,并使您的代码更具可读性,可伸缩性,并且像其他操作一样,将流和异步调用从UI代码中排除。

您的情况很简单:

CuPy Version          : 5.4.0
CUDA Root             : /usr/local/cuda-10.1
CUDA Build Version    : 10010
CUDA Driver Version   : 0
CUDA Runtime Version  : CUDARuntimeError('cudaErrorInsufficientDriver: CUDA driver version is insufficient for CUDA runtime version',)
cuDNN Build Version   : 7500
cuDNN Version         : 7500
NCCL Build Version    : None
NCCL Runtime Version  : None

通过示例来跟踪enum DownloadState { NO_DOWNLOAD, DOWNLOADING, SUCCESS } 调用网络API调用的状态的枚举。

async

一个BLoC类,它公开了一个流,并且在该类内部,我们创建了一个通过示例调用Network API的方法,当获取结果时,我们可以保存值,转换此值,使用流和其他方式发送到UI。在这里,在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 ); ); } } 中,完成Future对象之后,我们将一个downloadData值放入流中,这将迫使正在监听controller.stream的小部件在DownloadState帮助下在UI层中重建。如果我们从网络调用中收到一些错误,我们会将其放入流错误输出StreamBuilder中,并在UI层中使用controller.sink.addError属性进行检查。

在您的UI层中...

snapshot.hasError

和onPress事件中

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 );
)

使用这种方法,您可以删除UI层流对象和控制器,不需要setState调用,您将拥有一个包含业务逻辑和外部api调用的特定文件,这可以使我们拥有这种工作更加容易期货和信息流一起工作。

我希望能帮上忙。