diff --git a/dev/benchmarks/macrobenchmarks/lib/src/animated_placeholder.dart b/dev/benchmarks/macrobenchmarks/lib/src/animated_placeholder.dart index f6f071d72e..003e6b2869 100644 --- a/dev/benchmarks/macrobenchmarks/lib/src/animated_placeholder.dart +++ b/dev/benchmarks/macrobenchmarks/lib/src/animated_placeholder.dart @@ -58,7 +58,7 @@ class DelayedBase64Image extends ImageProvider { } @override - ImageStreamCompleter loadBuffer(int key, DecoderBufferCallback decode) { + ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { return MultiFrameImageStreamCompleter( codec: Future.delayed( delay, diff --git a/dev/integration_tests/web_e2e_tests/test_driver/cache_width_cache_height_integration.dart b/dev/integration_tests/web_e2e_tests/test_driver/cache_width_cache_height_integration.dart index 97df31bfa5..431e816e71 100644 --- a/dev/integration_tests/web_e2e_tests/test_driver/cache_width_cache_height_integration.dart +++ b/dev/integration_tests/web_e2e_tests/test_driver/cache_width_cache_height_integration.dart @@ -9,15 +9,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -// This class allows loadBuffer, a protected method, to be called with a custom -// DecoderBufferCallback function. +// This class allows loadImage, a protected method, to be called with a custom +// ImageDecoderCallback function. class LoadTestImageProvider extends ImageProvider { LoadTestImageProvider(this.provider); final ImageProvider provider; - ImageStreamCompleter testLoad(Object key, DecoderBufferCallback decode) { - return provider.loadBuffer(key, decode); + ImageStreamCompleter testLoad(Object key, ImageDecoderCallback decode) { + return provider.loadImage(key, decode); } @override @@ -26,7 +26,7 @@ class LoadTestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadBuffer(Object key, DecoderBufferCallback decode) { + ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) { throw UnimplementedError(); } } @@ -47,12 +47,15 @@ void main() { bool called = false; - Future decode(ui.ImmutableBuffer buffer, {int? cacheWidth, int? cacheHeight, bool allowUpscaling = false}) { - expect(cacheHeight, expectedCacheHeight); - expect(cacheWidth, expectedCacheWidth); - expect(allowUpscaling, false); - called = true; - return PaintingBinding.instance.instantiateImageCodecFromBuffer(buffer, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling); + Future decode(ui.ImmutableBuffer buffer, {ui.TargetImageSizeCallback? getTargetSize}) { + return PaintingBinding.instance.instantiateImageCodecWithSize(buffer, getTargetSize: (int intrinsicWidth, int intrinsicHeight) { + expect(getTargetSize, isNotNull); + final ui.TargetImageSize targetSize = getTargetSize!(intrinsicWidth, intrinsicHeight); + expect(targetSize.width, expectedCacheWidth); + expect(targetSize.height, expectedCacheHeight); + called = true; + return targetSize; + }); } final ImageProvider resizeImage = image.image; diff --git a/packages/flutter/lib/src/painting/_network_image_io.dart b/packages/flutter/lib/src/painting/_network_image_io.dart index 354670d869..827c781dd7 100644 --- a/packages/flutter/lib/src/painting/_network_image_io.dart +++ b/packages/flutter/lib/src/painting/_network_image_io.dart @@ -43,7 +43,7 @@ class NetworkImage extends image_provider.ImageProvider chunkEvents = StreamController(); return MultiFrameImageStreamCompleter( - codec: _loadAsync(key as NetworkImage, chunkEvents, null, decode), + codec: _loadAsync(key as NetworkImage, chunkEvents, decodeDeprecated: decode), chunkEvents: chunkEvents.stream, scale: key.scale, debugLabel: key.url, @@ -62,7 +62,26 @@ class NetworkImage extends image_provider.ImageProvider chunkEvents = StreamController(); return MultiFrameImageStreamCompleter( - codec: _loadAsync(key as NetworkImage, chunkEvents, decode, null), + codec: _loadAsync(key as NetworkImage, chunkEvents, decodeBufferDeprecated: decode), + chunkEvents: chunkEvents.stream, + scale: key.scale, + debugLabel: key.url, + informationCollector: () => [ + DiagnosticsProperty('Image provider', this), + DiagnosticsProperty('Image key', key), + ], + ); + } + + @override + ImageStreamCompleter loadImage(image_provider.NetworkImage key, image_provider.ImageDecoderCallback decode) { + // Ownership of this controller is handed off to [_loadAsync]; it is that + // method's responsibility to close the controller's stream when the image + // has been loaded or an error is thrown. + final StreamController chunkEvents = StreamController(); + + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key as NetworkImage, chunkEvents, decode: decode), chunkEvents: chunkEvents.stream, scale: key.scale, debugLabel: key.url, @@ -92,10 +111,11 @@ class NetworkImage extends image_provider.ImageProvider _loadAsync( NetworkImage key, - StreamController chunkEvents, - image_provider.DecoderBufferCallback? decode, - image_provider.DecoderCallback? decodeDepreacted, - ) async { + StreamController chunkEvents, { + image_provider.ImageDecoderCallback? decode, + image_provider.DecoderBufferCallback? decodeBufferDeprecated, + image_provider.DecoderCallback? decodeDeprecated, + }) async { try { assert(key == this); @@ -131,9 +151,12 @@ class NetworkImage extends image_provider.ImageProvider chunkEvents = StreamController(); + + return MultiFrameImageStreamCompleter( + chunkEvents: chunkEvents.stream, + codec: _loadAsync(key as NetworkImage, decode, null, null, chunkEvents), scale: key.scale, debugLabel: key.url, informationCollector: _imageStreamInformationCollector(key), @@ -106,8 +122,9 @@ class NetworkImage // directly in place of the typical `instantiateImageCodec` method. Future _loadAsync( NetworkImage key, - image_provider.DecoderBufferCallback? decode, - image_provider.DecoderCallback? decodeDepreacted, + image_provider.ImageDecoderCallback? decode, + image_provider.DecoderBufferCallback? decodeBufferDeprecated, + image_provider.DecoderCallback? decodeDeprecated, StreamController chunkEvents, ) async { assert(key == this); @@ -165,9 +182,12 @@ class NetworkImage if (decode != null) { final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes); return decode(buffer); + } else if (decodeBufferDeprecated != null) { + final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes); + return decodeBufferDeprecated(buffer); } else { - assert(decodeDepreacted != null); - return decodeDepreacted!(bytes); + assert(decodeDeprecated != null); + return decodeDeprecated!(bytes); } } else { // This API only exists in the web engine implementation and is not diff --git a/packages/flutter/lib/src/painting/binding.dart b/packages/flutter/lib/src/painting/binding.dart index acb5a2416c..fd54b3cd26 100644 --- a/packages/flutter/lib/src/painting/binding.dart +++ b/packages/flutter/lib/src/painting/binding.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui show Codec, ImmutableBuffer, instantiateImageCodec, instantiateImageCodecFromBuffer; +import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart' show ServicesBinding; @@ -100,7 +100,7 @@ mixin PaintingBinding on BindingBase, ServicesBinding { /// above its native resolution should prefer scaling the canvas the image is /// drawn into. @Deprecated( - 'Use instantiateImageCodecFromBuffer with an ImmutableBuffer instance instead. ' + 'Use instantiateImageCodecWithSize with an ImmutableBuffer instance instead. ' 'This feature was deprecated after v2.13.0-1.0.pre.', ) Future instantiateImageCodec( @@ -140,6 +140,10 @@ mixin PaintingBinding on BindingBase, ServicesBinding { /// unnecessary memory usage for images. Callers that wish to display an image /// above its native resolution should prefer scaling the canvas the image is /// drawn into. + @Deprecated( + 'Use instantiateImageCodecWithSize instead. ' + 'This feature was deprecated after v3.7.0-1.4.pre.', + ) Future instantiateImageCodecFromBuffer( ui.ImmutableBuffer buffer, { int? cacheWidth, @@ -156,6 +160,28 @@ mixin PaintingBinding on BindingBase, ServicesBinding { ); } + /// Calls through to [dart:ui.instantiateImageCodecWithSize] from [ImageCache]. + /// + /// The [buffer] parameter should be an [ui.ImmutableBuffer] instance which can + /// be acquired from [ui.ImmutableBuffer.fromUint8List] or + /// [ui.ImmutableBuffer.fromAsset]. + /// + /// The [getTargetSize] parameter, when specified, will be invoked and passed + /// the image's intrinsic size to determine the size to decode the image to. + /// The width and the height of the size it returns must be positive values + /// greater than or equal to 1, or null. It is valid to return a [TargetImageSize] + /// that specifies only one of `width` and `height` with the other remaining + /// null, in which case the omitted dimension will be scaled to maintain the + /// aspect ratio of the original dimensions. When both are null or omitted, + /// the image will be decoded at its native resolution (as will be the case if + /// the [getTargetSize] parameter is omitted). + Future instantiateImageCodecWithSize( + ui.ImmutableBuffer buffer, { + ui.TargetImageSizeCallback? getTargetSize, + }) { + return ui.instantiateImageCodecWithSize(buffer, getTargetSize: getTargetSize); + } + @override void evict(String asset) { super.evict(asset); diff --git a/packages/flutter/lib/src/painting/image_provider.dart b/packages/flutter/lib/src/painting/image_provider.dart index ec165388d5..a989271599 100644 --- a/packages/flutter/lib/src/painting/image_provider.dart +++ b/packages/flutter/lib/src/painting/image_provider.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:io'; -import 'dart:ui' as ui show Codec, ImmutableBuffer; +import 'dart:ui' as ui; import 'dart:ui' show Locale, Size, TextDirection; import 'package:flutter/foundation.dart'; @@ -175,12 +175,11 @@ class ImageConfiguration { /// * [ResizeImage], which uses this to override the `cacheWidth`, /// `cacheHeight`, and `allowUpscaling` parameters. @Deprecated( - 'Use DecoderBufferCallback with ImageProvider.loadBuffer instead. ' + 'Use ImageDecoderCallback with ImageProvider.loadImage instead. ' 'This feature was deprecated after v2.13.0-1.0.pre.', ) typedef DecoderCallback = Future Function(Uint8List buffer, {int? cacheWidth, int? cacheHeight, bool allowUpscaling}); - /// Performs the decode process for use in [ImageProvider.loadBuffer]. /// /// This callback allows decoupling of the `cacheWidth`, `cacheHeight`, and @@ -191,8 +190,25 @@ typedef DecoderCallback = Future Function(Uint8List buffer, {int? cach /// /// * [ResizeImage], which uses this to override the `cacheWidth`, /// `cacheHeight`, and `allowUpscaling` parameters. +@Deprecated( + 'Use ImageDecoderCallback with ImageProvider.loadImage instead. ' + 'This feature was deprecated after v3.7.0-1.4.pre.', +) typedef DecoderBufferCallback = Future Function(ui.ImmutableBuffer buffer, {int? cacheWidth, int? cacheHeight, bool allowUpscaling}); +/// Performs the decode process for use in [ImageProvider.loadImage]. +/// +/// This callback allows decoupling of the `getTargetSize` parameter from +/// implementations of [ImageProvider] that do not expose it. +/// +/// See also: +/// +/// * [ResizeImage], which uses this to load images at specific sizes. +typedef ImageDecoderCallback = Future Function( + ui.ImmutableBuffer buffer, { + ui.TargetImageSizeCallback? getTargetSize, +}); + /// Identifies an image without committing to the precise final asset. This /// allows a set of images to be identified and for the precise image to later /// be resolved based on the environment, e.g. the device pixel ratio. @@ -453,9 +469,9 @@ abstract class ImageProvider { return; } if (!didError) { + didError = true; errorCallback(obtainedKey, exception, stack); } - didError = true; } Future key; @@ -508,7 +524,22 @@ abstract class ImageProvider { } final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent( key, - () => loadBuffer(key, PaintingBinding.instance.instantiateImageCodecFromBuffer), + () { + ImageStreamCompleter result = loadImage(key, PaintingBinding.instance.instantiateImageCodecWithSize); + // This check exists as a fallback for backwards compatibility until the + // deprecated `loadBuffer()` method is removed. Until then, ImageProvider + // subclasses may have only overridden `loadBuffer()`, in which case the + // base implementation of `loadWithSize()` will return a sentinel value + // of type `_AbstractImageStreamCompleter`. + if (result is _AbstractImageStreamCompleter) { + result = loadBuffer(key, PaintingBinding.instance.instantiateImageCodecFromBuffer); + if (result is _AbstractImageStreamCompleter) { + // Same fallback as above but for the deprecated `load()` method. + result = load(key, PaintingBinding.instance.instantiateImageCodec); + } + } + return result; + }, onError: handleError, ); if (completer != null) { @@ -592,7 +623,7 @@ abstract class ImageProvider { /// * [ResizeImage], for modifying the key to account for cache dimensions. @protected @Deprecated( - 'Implement loadBuffer for faster image loading. ' + 'Implement loadImage for faster image loading. ' 'This feature was deprecated after v2.13.0-1.0.pre.', ) ImageStreamCompleter load(T key, DecoderCallback decode) { @@ -602,9 +633,10 @@ abstract class ImageProvider { /// Converts a key into an [ImageStreamCompleter], and begins fetching the /// image. /// - /// For backwards-compatibility the default implementation of this method calls - /// through to [ImageProvider.load]. However, implementors of this interface should - /// only override this method and not [ImageProvider.load], which is deprecated. + /// For backwards-compatibility the default implementation of this method returns + /// an object that will cause [resolveStreamForKey] to consult [load]. However, + /// implementors of this interface should only override this method and not + /// [load], which is deprecated. /// /// The [decode] callback provides the logic to obtain the codec for the /// image. @@ -613,14 +645,42 @@ abstract class ImageProvider { /// /// * [ResizeImage], for modifying the key to account for cache dimensions. @protected + @Deprecated( + 'Implement loadImage for image loading. ' + 'This feature was deprecated after v3.7.0-1.4.pre.', + ) ImageStreamCompleter loadBuffer(T key, DecoderBufferCallback decode) { - return load(key, PaintingBinding.instance.instantiateImageCodec); + return _AbstractImageStreamCompleter(); + } + + /// Converts a key into an [ImageStreamCompleter], and begins fetching the + /// image. + /// + /// For backwards-compatibility the default implementation of this method returns + /// an object that will cause [resolveStreamForKey] to consult [loadBuffer]. + /// However, implementors of this interface should only override this method + /// and not [loadBuffer], which is deprecated. + /// + /// The [decode] callback provides the logic to obtain the codec for the + /// image. + /// + /// See also: + /// + /// * [ResizeImage], for modifying the key to account for cache dimensions. + // TODO(tvolkert): make abstract (https://github.com/flutter/flutter/issues/119209) + @protected + ImageStreamCompleter loadImage(T key, ImageDecoderCallback decode) { + return _AbstractImageStreamCompleter(); } @override String toString() => '${objectRuntimeType(this, 'ImageConfiguration')}()'; } +/// A class that exists to facilitate backwards compatibility in the transition +/// from [ImageProvider.load] to [ImageProvider.loadBuffer] to [ImageProvider.loadImage] +class _AbstractImageStreamCompleter extends ImageStreamCompleter {} + /// Key for the image obtained by an [AssetImage] or [ExactAssetImage]. /// /// This is used to identify the precise resource in the [imageCache]. @@ -675,6 +735,24 @@ abstract class AssetBundleImageProvider extends ImageProvider [ + DiagnosticsProperty('Image provider', this), + DiagnosticsProperty('Image key', key), + ]; + return true; + }()); + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key, decode: decode), + scale: key.scale, + debugLabel: key.name, + informationCollector: collector, + ); + } + /// Converts a key into an [ImageStreamCompleter], and begins fetching the /// image. @override @@ -688,7 +766,7 @@ abstract class AssetBundleImageProvider extends ImageProvider _loadAsync(AssetBundleImageKey key, DecoderBufferCallback? decode, DecoderCallback? decodeDepreacted) async { + Future _loadAsync( + AssetBundleImageKey key, { + ImageDecoderCallback? decode, + DecoderBufferCallback? decodeBufferDeprecated, + DecoderCallback? decodeDeprecated, + }) async { if (decode != null) { - ui.ImmutableBuffer? buffer; + ui.ImmutableBuffer buffer; // Hot reload/restart could change whether an asset bundle or key in a // bundle are available, or if it is a network backed bundle. try { @@ -731,6 +814,18 @@ abstract class AssetBundleImageProvider extends ImageProvider { ); return decode(buffer, cacheWidth: width, cacheHeight: height, allowUpscaling: this.allowUpscaling); } + final ImageStreamCompleter completer = imageProvider.loadBuffer(key._providerCacheKey, decodeResize); if (!kReleaseMode) { completer.debugLabel = '${completer.debugLabel} - Resized(${key._width}×${key._height})'; @@ -857,6 +953,36 @@ class ResizeImage extends ImageProvider { return completer; } + @override + ImageStreamCompleter loadImage(ResizeImageKey key, ImageDecoderCallback decode) { + Future decodeResize(ui.ImmutableBuffer buffer, {ui.TargetImageSizeCallback? getTargetSize}) { + assert( + getTargetSize == null, + 'ResizeImage cannot be composed with another ImageProvider that applies ' + 'getTargetSize.', + ); + return decode(buffer, getTargetSize: (int intrinsicWidth, int intrinsicHeight) { + int? targetWidth = width; + int? targetHeight = height; + if (!allowUpscaling) { + if (targetWidth != null && targetWidth > intrinsicWidth) { + targetWidth = intrinsicWidth; + } + if (targetHeight != null && targetHeight > intrinsicHeight) { + targetHeight = intrinsicHeight; + } + } + return ui.TargetImageSize(width: targetWidth, height: targetHeight); + }); + } + + final ImageStreamCompleter completer = imageProvider.loadImage(key._providerCacheKey, decodeResize); + if (!kReleaseMode) { + completer.debugLabel = '${completer.debugLabel} - Resized(${key._width}×${key._height})'; + } + return completer; + } + @override Future obtainKey(ImageConfiguration configuration) { Completer? completer; @@ -921,6 +1047,9 @@ abstract class NetworkImage extends ImageProvider { @override ImageStreamCompleter loadBuffer(NetworkImage key, DecoderBufferCallback decode); + + @override + ImageStreamCompleter loadImage(NetworkImage key, ImageDecoderCallback decode); } /// Decodes the given [File] object as an image, associating it with the given @@ -953,7 +1082,7 @@ class FileImage extends ImageProvider { @override ImageStreamCompleter load(FileImage key, DecoderCallback decode) { return MultiFrameImageStreamCompleter( - codec: _loadAsync(key, null, decode), + codec: _loadAsync(key, decodeDeprecated: decode), scale: key.scale, debugLabel: key.file.path, informationCollector: () => [ @@ -965,7 +1094,7 @@ class FileImage extends ImageProvider { @override ImageStreamCompleter loadBuffer(FileImage key, DecoderBufferCallback decode) { return MultiFrameImageStreamCompleter( - codec: _loadAsync(key, decode, null), + codec: _loadAsync(key, decodeBufferDeprecated: decode), scale: key.scale, debugLabel: key.file.path, informationCollector: () => [ @@ -974,7 +1103,25 @@ class FileImage extends ImageProvider { ); } - Future _loadAsync(FileImage key, DecoderBufferCallback? decode, DecoderCallback? decodeDeprecated) async { + @override + @protected + ImageStreamCompleter loadImage(FileImage key, ImageDecoderCallback decode) { + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key, decode: decode), + scale: key.scale, + debugLabel: key.file.path, + informationCollector: () => [ + ErrorDescription('Path: ${file.path}'), + ], + ); + } + + Future _loadAsync( + FileImage key, { + ImageDecoderCallback? decode, + DecoderBufferCallback? decodeBufferDeprecated, + DecoderCallback? decodeDeprecated, + }) async { assert(key == this); // TODO(jonahwilliams): making this sync caused test failures that seem to @@ -993,6 +1140,12 @@ class FileImage extends ImageProvider { } return decode(await ui.ImmutableBuffer.fromUint8List(await file.readAsBytes())); } + if (decodeBufferDeprecated != null) { + if (file.runtimeType == File) { + return decodeBufferDeprecated(await ui.ImmutableBuffer.fromFilePath(file.path)); + } + return decodeBufferDeprecated(await ui.ImmutableBuffer.fromUint8List(await file.readAsBytes())); + } return decodeDeprecated!(await file.readAsBytes()); } @@ -1058,7 +1211,7 @@ class MemoryImage extends ImageProvider { @override ImageStreamCompleter load(MemoryImage key, DecoderCallback decode) { return MultiFrameImageStreamCompleter( - codec: _loadAsync(key, null, decode), + codec: _loadAsync(key, decodeDeprecated: decode), scale: key.scale, debugLabel: 'MemoryImage(${describeIdentity(key.bytes)})', ); @@ -1067,19 +1220,37 @@ class MemoryImage extends ImageProvider { @override ImageStreamCompleter loadBuffer(MemoryImage key, DecoderBufferCallback decode) { return MultiFrameImageStreamCompleter( - codec: _loadAsync(key, decode, null), + codec: _loadAsync(key, decodeBufferDeprecated: decode), scale: key.scale, debugLabel: 'MemoryImage(${describeIdentity(key.bytes)})', ); } - Future _loadAsync(MemoryImage key, DecoderBufferCallback? decode, DecoderCallback? decodeDepreacted) async { + @override + ImageStreamCompleter loadImage(MemoryImage key, ImageDecoderCallback decode) { + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key, decode: decode), + scale: key.scale, + debugLabel: 'MemoryImage(${describeIdentity(key.bytes)})', + ); + } + + Future _loadAsync( + MemoryImage key, { + ImageDecoderCallback? decode, + DecoderBufferCallback? decodeBufferDeprecated, + DecoderCallback? decodeDeprecated, + }) async { assert(key == this); if (decode != null) { final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes); return decode(buffer); } - return decodeDepreacted!(bytes); + if (decodeBufferDeprecated != null) { + final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes); + return decodeBufferDeprecated(buffer); + } + return decodeDeprecated!(bytes); } @override diff --git a/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart b/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart index 7ea73ac7a8..4009be91ed 100644 --- a/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart +++ b/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart @@ -111,6 +111,9 @@ class ScrollAwareImageProvider extends ImageProvider { @override ImageStreamCompleter loadBuffer(T key, DecoderBufferCallback decode) => imageProvider.loadBuffer(key, decode); + @override + ImageStreamCompleter loadImage(T key, ImageDecoderCallback decode) => imageProvider.loadImage(key, decode); + @override Future obtainKey(ImageConfiguration configuration) => imageProvider.obtainKey(configuration); } diff --git a/packages/flutter/test/painting/image_test_utils.dart b/packages/flutter/test/painting/image_test_utils.dart index 5894efe98d..847984663e 100644 --- a/packages/flutter/test/painting/image_test_utils.dart +++ b/packages/flutter/test/painting/image_test_utils.dart @@ -30,11 +30,16 @@ class TestImageProvider extends ImageProvider { @override ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) { - throw UnsupportedError('Use ImageProvider.loadBuffer instead.'); + throw UnsupportedError('Use ImageProvider.loadImage instead.'); } @override ImageStreamCompleter loadBuffer(TestImageProvider key, DecoderBufferCallback decode) { + throw UnsupportedError('Use ImageProvider.loadImage instead.'); + } + + @override + ImageStreamCompleter loadImage(TestImageProvider key, ImageDecoderCallback decode) { loadCallCount += 1; return OneFrameImageStreamCompleter(_completer.future); } diff --git a/packages/flutter/test/painting/mocks_for_image_cache.dart b/packages/flutter/test/painting/mocks_for_image_cache.dart index 77b3242799..1273faa4c5 100644 --- a/packages/flutter/test/painting/mocks_for_image_cache.dart +++ b/packages/flutter/test/painting/mocks_for_image_cache.dart @@ -85,6 +85,11 @@ Future extractOneFrame(ImageStream stream) { } class ErrorImageProvider extends ImageProvider { + @override + ImageStreamCompleter loadImage(ErrorImageProvider key, ImageDecoderCallback decode) { + throw Error(); + } + @override ImageStreamCompleter loadBuffer(ErrorImageProvider key, DecoderBufferCallback decode) { throw Error(); @@ -103,10 +108,15 @@ class ErrorImageProvider extends ImageProvider { class ObtainKeyErrorImageProvider extends ImageProvider { @override - ImageStreamCompleter loadBuffer(ObtainKeyErrorImageProvider key, DecoderBufferCallback decode) { + ImageStreamCompleter loadImage(ObtainKeyErrorImageProvider key, ImageDecoderCallback decode) { throw Error(); } + @override + ImageStreamCompleter loadBuffer(ObtainKeyErrorImageProvider key, DecoderBufferCallback decode) { + throw UnimplementedError(); + } + @override Future obtainKey(ImageConfiguration configuration) { throw Error(); @@ -120,10 +130,15 @@ class ObtainKeyErrorImageProvider extends ImageProvider { @override - ImageStreamCompleter loadBuffer(LoadErrorImageProvider key, DecoderBufferCallback decode) { + ImageStreamCompleter loadImage(LoadErrorImageProvider key, ImageDecoderCallback decode) { throw Error(); } + @override + ImageStreamCompleter loadBuffer(LoadErrorImageProvider key, DecoderBufferCallback decode) { + throw UnimplementedError(); + } + @override Future obtainKey(ImageConfiguration configuration) { return SynchronousFuture(this); diff --git a/packages/flutter/test/widgets/image_resolution_test.dart b/packages/flutter/test/widgets/image_resolution_test.dart index 3bc24b1cd3..fe836c1ed4 100644 --- a/packages/flutter/test/widgets/image_resolution_test.dart +++ b/packages/flutter/test/widgets/image_resolution_test.dart @@ -85,7 +85,7 @@ class TestAssetImage extends AssetImage { final Map images; @override - ImageStreamCompleter loadBuffer(AssetBundleImageKey key, DecoderBufferCallback decode) { + ImageStreamCompleter loadImage(AssetBundleImageKey key, ImageDecoderCallback decode) { late ImageInfo imageInfo; key.bundle.load(key.name).then((ByteData data) { final ui.Image image = images[scaleOf(data)]!; diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index 52addf0d38..232a45bd71 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -2173,7 +2173,7 @@ class _DebouncingImageProvider extends ImageProvider { Future obtainKey(ImageConfiguration configuration) => imageProvider.obtainKey(configuration); @override - ImageStreamCompleter loadBuffer(Object key, DecoderBufferCallback decode) => imageProvider.loadBuffer(key, decode); + ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) => imageProvider.loadImage(key, decode); } class _FailingImageProvider extends ImageProvider { diff --git a/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart b/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart index a0e2be0bbb..51fa9d85ef 100644 --- a/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart +++ b/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart @@ -322,7 +322,7 @@ void main() { // If we miss the early return, we will fail. testImageProvider.complete(); - imageCache.putIfAbsent(testImageProvider, () => testImageProvider.loadBuffer(testImageProvider, PaintingBinding.instance.instantiateImageCodecFromBuffer)); + imageCache.putIfAbsent(testImageProvider, () => testImageProvider.loadImage(testImageProvider, PaintingBinding.instance.instantiateImageCodecWithSize)); // We've stopped scrolling fast. physics.recommendDeferredLoadingValue = false; await tester.idle(); @@ -377,7 +377,7 @@ void main() { // Complete the original image while we're still scrolling fast. testImageProvider.complete(); - stream.setCompleter(testImageProvider.loadBuffer(testImageProvider, PaintingBinding.instance.instantiateImageCodecFromBuffer)); + stream.setCompleter(testImageProvider.loadImage(testImageProvider, PaintingBinding.instance.instantiateImageCodecWithSize)); // Verify that this hasn't changed the cache state yet expect(imageCache.containsKey(testImageProvider), false);