diff --git a/mobile/lib/presentation/widgets/images/image_provider.dart b/mobile/lib/presentation/widgets/images/image_provider.dart index bf29f9482f..1d87fa404e 100644 --- a/mobile/lib/presentation/widgets/images/image_provider.dart +++ b/mobile/lib/presentation/widgets/images/image_provider.dart @@ -19,6 +19,7 @@ mixin CancellableImageProviderMixin on CancellableImageProvide static final _log = Logger('CancellableImageProviderMixin'); bool isCancelled = false; + bool isFinished = false; ImageRequest? request; CancelableOperation? cachedOperation; @@ -53,13 +54,15 @@ mixin CancellableImageProviderMixin on CancellableImageProvide Stream loadRequest(ImageRequest request, ImageDecoderCallback decode, {bool evictOnError = true}) async* { if (isCancelled) { this.request = null; - PaintingBinding.instance.imageCache.evict(this); return; } try { final image = await request.load(decode); - if ((image == null && evictOnError) || isCancelled) { + if (isCancelled) { + return; + } + if (image == null && evictOnError) { PaintingBinding.instance.imageCache.evict(this); return; } else if (image == null) { @@ -67,6 +70,9 @@ mixin CancellableImageProviderMixin on CancellableImageProvide } yield image; } catch (e, stack) { + if (isCancelled) { + return; + } if (evictOnError) { PaintingBinding.instance.imageCache.evict(this); rethrow; @@ -80,20 +86,24 @@ mixin CancellableImageProviderMixin on CancellableImageProvide Future loadCodecRequest(ImageRequest request) async { if (isCancelled) { this.request = null; - PaintingBinding.instance.imageCache.evict(this); return null; } try { final codec = await request.loadCodec(); - if (codec == null || isCancelled) { + if (isCancelled) { codec?.dispose(); + return null; + } + if (codec == null) { PaintingBinding.instance.imageCache.evict(this); return null; } return codec; } catch (e) { - PaintingBinding.instance.imageCache.evict(this); + if (!isCancelled) { + PaintingBinding.instance.imageCache.evict(this); + } rethrow; } finally { this.request = null; @@ -121,6 +131,8 @@ mixin CancellableImageProviderMixin on CancellableImageProvide @override void cancel() { isCancelled = true; + final hasActiveWork = !isFinished; + final request = this.request; if (request != null) { this.request = null; @@ -132,6 +144,10 @@ mixin CancellableImageProviderMixin on CancellableImageProvide cachedOperation = null; operation.cancel(); } + + if (hasActiveWork) { + PaintingBinding.instance.imageCache.evict(this); + } } } diff --git a/mobile/lib/presentation/widgets/images/local_image_provider.dart b/mobile/lib/presentation/widgets/images/local_image_provider.dart index 1ed2c361ff..d4f829bed5 100644 --- a/mobile/lib/presentation/widgets/images/local_image_provider.dart +++ b/mobile/lib/presentation/widgets/images/local_image_provider.dart @@ -100,7 +100,6 @@ class LocalFullImageProvider extends CancellableImageProvider _animatedCodec(LocalFullImageProvider key, ImageDecoderCallback decode) async* { yield* initialImageStream(); if (isCancelled) { - PaintingBinding.instance.imageCache.evict(this); return; } @@ -143,7 +142,6 @@ class LocalFullImageProvider extends CancellableImageProvider _animatedCodec(RemoteFullImageProvider key, ImageDecoderCallback decode) async* { yield* initialImageStream(); if (isCancelled) { - PaintingBinding.instance.imageCache.evict(this); return; } @@ -142,7 +141,6 @@ class RemoteFullImageProvider extends CancellableImageProvider