John Joe
John Joe

Reputation: 12803

The following StateError was thrown by an image listener: Bad state: Future already completed

Why I will receive this exception?

════════ Exception caught by image resource service ════════════════════════════
The following StateError was thrown by an image listener:
Bad state: Future already completed

When the exception was thrown, this was the stack
#1      _xxxState.setup.<anonymous closure>
xxx/ui/xxx.dart:209
#2      ImageStreamCompleter.setImage
package:flutter/…/painting/image_stream.dart:633
#3      MultiImageStreamCompleter._emitFrame
package:cached_network_image/…/image_provider/multi_image_stream_completer.dart:156
#4      MultiImageStreamCompleter._decodeNextFrameAndSchedule
package:cached_network_image/…/image_provider/multi_image_stream_completer.dart:141
<asynchronous suspension>
(elided one frame from dart:async)

Code

initState(){
   _refresh();
}

_refresh() async {
   ...
   await setUp();
}

 setup() async {
  
    var data = await _bloc.selectFloorPlan(floorPlanId);

    Image image = Image(image: CachedNetworkImageProvider(data));

    Completer<ui.Image> completer = Completer<ui.Image>();
    image.image
        .resolve(ImageConfiguration())
        .addListener(ImageStreamListener((ImageInfo image, bool _) {
      completer.complete(image.image);

      if (completer.isCompleted) {
        if (mounted) {
          floorPlanAnnotationUtil.updateValues(
            containerHeight: containerFixedHeight,
            containerWidth: MediaQuery.of(context).size.width -
                20, // minus the container padding 10 * 2
            imageHeight:
                DevicePixelUtil.toDevicePixel(context, image.image.height),
            imageWidth:
                DevicePixelUtil.toDevicePixel(context, image.image.width),
          );
        }

        // setState(() {});
      }
    }));
  }

The error pointed to this line

 completer.complete(image.image);

Upvotes: 1

Views: 980

Answers (1)

puelo
puelo

Reputation: 6057

It looks like you are using https://pub.dev/packages/cached_network_image, which internally uses https://pub.dev/packages/flutter_cache_manager. The default Cache Manager can add multiple (relevant) events to the stream. For example if the image in the cache is stale it first emits the cached image and afterwards it emits the newly downloaded image again. You are probably seeing the effect here since your Completer can only be completed once.

Upvotes: 1

Related Questions