在今天编写vision类的时候,遇到这么一个问题,我们需要从Image Widget中获取到图像的二进制数据。观察过源码之后发现,Image是对ImageProvider中的数据流进行了注册监听,用到了回调。我们采用同样的方式去获取ImageInfo对象,虽然ImagePrivider对我们提供了ImageStream,但是ImageStream类并不是继承自Stream,所以对于Stream提供的那些方法自然不能奏效。只能采取ImageStream提供的方案:ImageStreamListener,但是这样一来我们就只能通过ImageStreamListener参数中的回调函数来处理返回的数据,这样既不利于我们思维理解,也不利于数据的处理,那么有没有一种办法是可以将这种回调方式转化为Future返回值呢?答案当然是存在这种办法的。

解决方法如下:

	final Completer<ByteData> completer = Completer();
    ImageStreamListener listener;
    listener = ImageStreamListener((ImageInfo image, bool synchronousCall) {
      completer.complete(image.image.toByteData());
      newStream.removeListener(listener);
    });
    newStream.addListener(listener);
    final bytes = (await completer.future).buffer.asUint8List();
    final visionImage = FirebaseVisionImage.fromBytes(
        bytes,
        FirebaseVisionImageMetadata(
          size: Size(widget.width, widget.height),
          rawFormat: null,
          planeData: null,
    ));

其中Dartlang中的Completer对象就可以将这种回调传值的方式转化为Future返回值,仔细想一下,是不是和Java中的CountDownLatch可以起到的作用是不是很类似呢。