diff --git a/packages/flutter/lib/src/painting/_network_image_io.dart b/packages/flutter/lib/src/painting/_network_image_io.dart index 5221279c61..05dd8cb722 100644 --- a/packages/flutter/lib/src/painting/_network_image_io.dart +++ b/packages/flutter/lib/src/painting/_network_image_io.dart @@ -13,9 +13,6 @@ import 'debug.dart'; import 'image_provider.dart' as image_provider; import 'image_stream.dart'; -// Method signature for _loadAsync decode callbacks. -typedef _SimpleDecoderCallback = Future Function(ui.ImmutableBuffer buffer); - /// The dart:io implementation of [image_provider.NetworkImage]. @immutable class NetworkImage extends image_provider.ImageProvider implements image_provider.NetworkImage { @@ -38,6 +35,25 @@ class NetworkImage extends image_provider.ImageProvider(this); } + @override + ImageStreamCompleter load(image_provider.NetworkImage key, image_provider.DecoderCallback 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, decodeDeprecated: decode), + chunkEvents: chunkEvents.stream, + scale: key.scale, + debugLabel: key.url, + informationCollector: () => [ + DiagnosticsProperty('Image provider', this), + DiagnosticsProperty('Image key', key), + ], + ); + } + @override ImageStreamCompleter loadBuffer(image_provider.NetworkImage key, image_provider.DecoderBufferCallback decode) { // Ownership of this controller is handed off to [_loadAsync]; it is that @@ -46,7 +62,7 @@ class NetworkImage extends image_provider.ImageProvider chunkEvents = StreamController(); return MultiFrameImageStreamCompleter( - codec: _loadAsync(key as NetworkImage, chunkEvents, decode: decode), + codec: _loadAsync(key as NetworkImage, chunkEvents, decodeBufferDeprecated: decode), chunkEvents: chunkEvents.stream, scale: key.scale, debugLabel: key.url, @@ -96,7 +112,9 @@ class NetworkImage extends image_provider.ImageProvider _loadAsync( NetworkImage key, StreamController chunkEvents, { - required _SimpleDecoderCallback decode, + image_provider.ImageDecoderCallback? decode, + image_provider.DecoderBufferCallback? decodeBufferDeprecated, + image_provider.DecoderCallback? decodeDeprecated, }) async { try { assert(key == this); @@ -130,7 +148,16 @@ class NetworkImage extends image_provider.ImageProvider Function(ui.ImmutableBuffer buffer); - /// Default HTTP client. web.XMLHttpRequest _httpClient() { return web.XMLHttpRequest(); @@ -57,6 +54,23 @@ class NetworkImage return SynchronousFuture(this); } + @override + ImageStreamCompleter load(image_provider.NetworkImage key, image_provider.DecoderCallback 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( + chunkEvents: chunkEvents.stream, + codec: _loadAsync(key as NetworkImage, null, null, decode, chunkEvents), + scale: key.scale, + debugLabel: key.url, + informationCollector: _imageStreamInformationCollector(key), + ); + } + @override ImageStreamCompleter loadBuffer(image_provider.NetworkImage key, image_provider.DecoderBufferCallback decode) { // Ownership of this controller is handed off to [_loadAsync]; it is that @@ -67,7 +81,7 @@ class NetworkImage return MultiFrameImageStreamCompleter( chunkEvents: chunkEvents.stream, - codec: _loadAsync(key as NetworkImage, decode, chunkEvents), + codec: _loadAsync(key as NetworkImage, null, decode, null, chunkEvents), scale: key.scale, debugLabel: key.url, informationCollector: _imageStreamInformationCollector(key), @@ -83,7 +97,7 @@ class NetworkImage return MultiFrameImageStreamCompleter( chunkEvents: chunkEvents.stream, - codec: _loadAsync(key as NetworkImage, decode, chunkEvents), + codec: _loadAsync(key as NetworkImage, decode, null, null, chunkEvents), scale: key.scale, debugLabel: key.url, informationCollector: _imageStreamInformationCollector(key), @@ -107,7 +121,9 @@ class NetworkImage // directly in place of the typical `instantiateImageCodec` method. Future _loadAsync( NetworkImage key, - _SimpleDecoderCallback decode, + image_provider.ImageDecoderCallback? decode, + image_provider.DecoderBufferCallback? decodeBufferDeprecated, + image_provider.DecoderCallback? decodeDeprecated, StreamController chunkEvents, ) async { assert(key == this); @@ -162,7 +178,17 @@ class NetworkImage throw image_provider.NetworkImageLoadException( statusCode: request.status, uri: resolved); } - return decode(await ui.ImmutableBuffer.fromUint8List(bytes)); + + 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(decodeDeprecated != null); + return decodeDeprecated!(bytes); + } } else { // This API only exists in the web engine implementation and is not // contained in the analyzer summary for Flutter. diff --git a/packages/flutter/lib/src/painting/binding.dart b/packages/flutter/lib/src/painting/binding.dart index 02efc9082a..880db6d33f 100644 --- a/packages/flutter/lib/src/painting/binding.dart +++ b/packages/flutter/lib/src/painting/binding.dart @@ -78,6 +78,47 @@ mixin PaintingBinding on BindingBase, ServicesBinding { @protected ImageCache createImageCache() => ImageCache(); + /// Calls through to [dart:ui.instantiateImageCodec] from [ImageCache]. + /// + /// This method is deprecated. use [instantiateImageCodecFromBuffer] with an + /// [ImmutableBuffer] instance instead of this method. + /// + /// The `cacheWidth` and `cacheHeight` parameters, when specified, indicate + /// the size to decode the image to. + /// + /// Both `cacheWidth` and `cacheHeight` must be positive values greater than + /// or equal to 1, or null. It is valid to specify only one of `cacheWidth` + /// and `cacheHeight` 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. + /// + /// The `allowUpscaling` parameter determines whether the `cacheWidth` or + /// `cacheHeight` parameters are clamped to the intrinsic width and height of + /// the original image. By default, the dimensions are clamped to avoid + /// 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 with an ImmutableBuffer instance instead. ' + 'This feature was deprecated after v2.13.0-1.0.pre.', + ) + Future instantiateImageCodec( + Uint8List bytes, { + int? cacheWidth, + int? cacheHeight, + bool allowUpscaling = false, + }) { + assert(cacheWidth == null || cacheWidth > 0); + assert(cacheHeight == null || cacheHeight > 0); + return ui.instantiateImageCodec( + bytes, + targetWidth: cacheWidth, + targetHeight: cacheHeight, + allowUpscaling: allowUpscaling, + ); + } + /// Calls through to [dart:ui.instantiateImageCodecFromBuffer] from [ImageCache]. /// /// The [buffer] parameter should be an [ui.ImmutableBuffer] instance which can diff --git a/packages/flutter/lib/src/painting/image_decoder.dart b/packages/flutter/lib/src/painting/image_decoder.dart index 328c840f73..39d926ee34 100644 --- a/packages/flutter/lib/src/painting/image_decoder.dart +++ b/packages/flutter/lib/src/painting/image_decoder.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:typed_data'; -import 'dart:ui' as ui show Codec, FrameInfo, Image, ImmutableBuffer; +import 'dart:ui' as ui show Codec, FrameInfo, Image; import 'binding.dart'; @@ -17,11 +17,10 @@ import 'binding.dart'; /// [instantiateImageCodec] if support for animated images is necessary. /// /// This function differs from [ui.decodeImageFromList] in that it defers to -/// [PaintingBinding.instantiateImageCodecWithSize], and therefore can be mocked -/// in tests. +/// [PaintingBinding.instantiateImageCodec], and therefore can be mocked in +/// tests. Future decodeImageFromList(Uint8List bytes) async { - final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes); - final ui.Codec codec = await PaintingBinding.instance.instantiateImageCodecWithSize(buffer); + final ui.Codec codec = await PaintingBinding.instance.instantiateImageCodec(bytes); final ui.FrameInfo frameInfo = await codec.getNextFrame(); return frameInfo.image; } diff --git a/packages/flutter/lib/src/painting/image_provider.dart b/packages/flutter/lib/src/painting/image_provider.dart index b7067c2583..54e21cc597 100644 --- a/packages/flutter/lib/src/painting/image_provider.dart +++ b/packages/flutter/lib/src/painting/image_provider.dart @@ -160,6 +160,25 @@ class ImageConfiguration { } } +/// Performs the decode process for use in [ImageProvider.load]. +/// +/// This typedef is deprecated. Use [ImageDecoderCallback] with +/// [ImageProvider.loadImage] instead. +/// +/// This callback allows decoupling of the `cacheWidth`, `cacheHeight`, and +/// `allowUpscaling` parameters from implementations of [ImageProvider] that do +/// not expose them. +/// +/// See also: +/// +/// * [ResizeImage], which uses this to override the `cacheWidth`, +/// `cacheHeight`, and `allowUpscaling` parameters. +@Deprecated( + '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 @@ -176,9 +195,6 @@ class ImageConfiguration { ) typedef DecoderBufferCallback = Future Function(ui.ImmutableBuffer buffer, {int? cacheWidth, int? cacheHeight, bool allowUpscaling}); -// Method signature for _loadAsync decode callbacks. -typedef _SimpleDecoderCallback = Future Function(ui.ImmutableBuffer buffer); - /// Performs the decode process for use in [ImageProvider.loadImage]. /// /// This callback allows decoupling of the `getTargetSize` parameter from @@ -234,7 +250,7 @@ typedef ImageDecoderCallback = Future Function( /// from the cache if possible, or call [loadImage] to fetch the encoded image /// bytes and schedule decoding. /// 4. The [loadImage] method is responsible for both fetching the encoded bytes -/// and decoding them using the provided [ImageDecoderCallback]. It is called +/// and decoding them using the provided [DecoderCallback]. It is called /// in a context that uses the [ImageErrorListener] to report errors back. /// /// Subclasses normally only have to implement the [loadImage] and [obtainKey] @@ -349,10 +365,10 @@ abstract class ImageProvider { /// /// This is the public entry-point of the [ImageProvider] class hierarchy. /// - /// Subclasses should implement [obtainKey] and [loadImage], which are used by - /// this method. If they need to change the implementation of [ImageStream] - /// used, they should override [createStream]. If they need to manage the - /// actual resolution of the image, they should override [resolveStreamForKey]. + /// Subclasses should implement [obtainKey] and [load], which are used by this + /// method. If they need to change the implementation of [ImageStream] used, + /// they should override [createStream]. If they need to manage the actual + /// resolution of the image, they should override [resolveStreamForKey]. /// /// See the Lifecycle documentation on [ImageProvider] for more information. @nonVirtual @@ -526,6 +542,10 @@ abstract class ImageProvider { // 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; }, @@ -590,17 +610,39 @@ abstract class ImageProvider { /// that describes the precise image to load. /// /// The type of the key is determined by the subclass. It is a value that - /// unambiguously identifies the image (_including its scale_) that the - /// [loadImage] method will fetch. Different [ImageProvider]s given the same - /// constructor arguments and [ImageConfiguration] objects should return keys - /// that are '==' to each other (possibly by using a class for the key that - /// itself implements [==]). + /// unambiguously identifies the image (_including its scale_) that the [load] + /// method will fetch. Different [ImageProvider]s given the same constructor + /// arguments and [ImageConfiguration] objects should return keys that are + /// '==' to each other (possibly by using a class for the key that itself + /// implements [==]). /// /// If the result can be determined synchronously, this function should return /// a [SynchronousFuture]. This allows image resolution to progress /// synchronously during a frame rather than delaying image loading. Future obtainKey(ImageConfiguration configuration); + /// Converts a key into an [ImageStreamCompleter], and begins fetching the + /// image. + /// + /// This method is deprecated. Implement [loadImage] for faster image + /// loading. Only one of [load] and [loadImage] must be implemented, and + /// [loadImage] is preferred. + /// + /// 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. + @protected + @Deprecated( + 'Implement loadImage for faster image loading. ' + 'This feature was deprecated after v2.13.0-1.0.pre.', + ) + ImageStreamCompleter load(T key, DecoderCallback decode) { + throw UnsupportedError('Implement loadImage for faster image loading'); + } + /// Converts a key into an [ImageStreamCompleter], and begins fetching the /// image. /// @@ -734,7 +776,25 @@ abstract class AssetBundleImageProvider extends ImageProvider [ + DiagnosticsProperty('Image provider', this), + DiagnosticsProperty('Image key', key), + ]; + return true; + }()); + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key, decodeDeprecated: decode), scale: key.scale, debugLabel: key.name, informationCollector: collector, @@ -744,22 +804,48 @@ abstract class AssetBundleImageProvider extends ImageProvider _loadAsync( AssetBundleImageKey key, { - required _SimpleDecoderCallback decode, + ImageDecoderCallback? decode, + DecoderBufferCallback? decodeBufferDeprecated, + DecoderCallback? decodeDeprecated, }) async { - final ui.ImmutableBuffer buffer; + if (decode != null) { + 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 { + buffer = await key.bundle.loadBuffer(key.name); + } on FlutterError { + PaintingBinding.instance.imageCache.evict(key); + rethrow; + } + return decode(buffer); + } + if (decodeBufferDeprecated != null) { + 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 { + buffer = await key.bundle.loadBuffer(key.name); + } on FlutterError { + PaintingBinding.instance.imageCache.evict(key); + rethrow; + } + return decodeBufferDeprecated(buffer); + } + ByteData data; // 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 { - buffer = await key.bundle.loadBuffer(key.name); + data = await key.bundle.load(key.name); } on FlutterError { PaintingBinding.instance.imageCache.evict(key); rethrow; } - return decode(buffer); + return decodeDeprecated!(data.buffer.asUint8List()); } } @@ -1251,6 +1337,28 @@ class ResizeImage extends ImageProvider { return provider; } + @override + @Deprecated( + 'Implement loadImage for faster image loading. ' + 'This feature was deprecated after v2.13.0-1.0.pre.', + ) + ImageStreamCompleter load(ResizeImageKey key, DecoderCallback decode) { + Future decodeResize(Uint8List buffer, {int? cacheWidth, int? cacheHeight, bool? allowUpscaling}) { + assert( + cacheWidth == null && cacheHeight == null && allowUpscaling == null, + 'ResizeImage cannot be composed with another ImageProvider that applies ' + 'cacheWidth, cacheHeight, or allowUpscaling.', + ); + return decode(buffer, cacheWidth: width, cacheHeight: height, allowUpscaling: this.allowUpscaling); + } + final ImageStreamCompleter completer = imageProvider.load(key._providerCacheKey, decodeResize); + if (!kReleaseMode) { + completer.debugLabel = '${completer.debugLabel} - Resized(${key._width}×${key._height})'; + } + _configureErrorListener(completer, key); + return completer; + } + @override @Deprecated( 'Implement loadImage for image loading. ' @@ -1386,11 +1494,11 @@ class ResizeImage extends ImageProvider { /// /// The image will be cached regardless of cache headers from the server. /// -/// When a network image is used on the Web platform, the `getTargetSize` -/// parameter of the [ImageDecoderCallback] is only supported when the -/// application is running with the CanvasKit renderer. When the application is -/// using the HTML renderer, the web engine delegates image decoding of network -/// images to the Web, which does not support custom decode sizes. +/// When a network image is used on the Web platform, the `cacheWidth` and +/// `cacheHeight` parameters of the [DecoderCallback] are only supported when the +/// application is running with the CanvasKit renderer. When the application is using +/// the HTML renderer, the web engine delegates image decoding of network images to the Web, +/// which does not support custom decode sizes. /// /// See also: /// @@ -1417,6 +1525,9 @@ abstract class NetworkImage extends ImageProvider { /// When running Flutter on the web, headers are not used. Map? get headers; + @override + ImageStreamCompleter load(NetworkImage key, DecoderCallback decode); + @override ImageStreamCompleter loadBuffer(NetworkImage key, DecoderBufferCallback decode); @@ -1451,10 +1562,22 @@ class FileImage extends ImageProvider { return SynchronousFuture(this); } + @override + ImageStreamCompleter load(FileImage key, DecoderCallback decode) { + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key, decodeDeprecated: decode), + scale: key.scale, + debugLabel: key.file.path, + informationCollector: () => [ + ErrorDescription('Path: ${file.path}'), + ], + ); + } + @override ImageStreamCompleter loadBuffer(FileImage key, DecoderBufferCallback decode) { return MultiFrameImageStreamCompleter( - codec: _loadAsync(key, decode: decode), + codec: _loadAsync(key, decodeBufferDeprecated: decode), scale: key.scale, debugLabel: key.file.path, informationCollector: () => [ @@ -1478,9 +1601,12 @@ class FileImage extends ImageProvider { Future _loadAsync( FileImage key, { - required _SimpleDecoderCallback decode, + ImageDecoderCallback? decode, + DecoderBufferCallback? decodeBufferDeprecated, + DecoderCallback? decodeDeprecated, }) async { assert(key == this); + // TODO(jonahwilliams): making this sync caused test failures that seem to // indicate that we can fail to call evict unless at least one await has // occurred in the test. @@ -1491,9 +1617,19 @@ class FileImage extends ImageProvider { PaintingBinding.instance.imageCache.evict(key); throw StateError('$file is empty and cannot be loaded as an image.'); } - return (file.runtimeType == File) - ? decode(await ui.ImmutableBuffer.fromFilePath(file.path)) - : decode(await ui.ImmutableBuffer.fromUint8List(await file.readAsBytes())); + if (decode != null) { + if (file.runtimeType == File) { + return decode(await ui.ImmutableBuffer.fromFilePath(file.path)); + } + 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()); } @override @@ -1519,8 +1655,8 @@ class FileImage extends ImageProvider { /// The provided [bytes] buffer should not be changed after it is provided /// to a [MemoryImage]. To provide an [ImageStream] that represents an image /// that changes over time, consider creating a new subclass of [ImageProvider] -/// whose [loadImage] method returns a subclass of [ImageStreamCompleter] that -/// can handle providing multiple images. +/// whose [load] method returns a subclass of [ImageStreamCompleter] that can +/// handle providing multiple images. /// /// See also: /// @@ -1539,7 +1675,7 @@ class MemoryImage extends ImageProvider { /// /// See also: /// - /// * [PaintingBinding.instantiateImageCodecWithSize] + /// * [PaintingBinding.instantiateImageCodec] final Uint8List bytes; /// The scale to place in the [ImageInfo] object of the image. @@ -1556,10 +1692,18 @@ class MemoryImage extends ImageProvider { } @override - ImageStreamCompleter loadBuffer(MemoryImage key, DecoderBufferCallback decode) { - assert(key == this); + ImageStreamCompleter load(MemoryImage key, DecoderCallback decode) { return MultiFrameImageStreamCompleter( - codec: _loadAsync(key, decode: decode), + codec: _loadAsync(key, decodeDeprecated: decode), + scale: key.scale, + debugLabel: 'MemoryImage(${describeIdentity(key.bytes)})', + ); + } + + @override + ImageStreamCompleter loadBuffer(MemoryImage key, DecoderBufferCallback decode) { + return MultiFrameImageStreamCompleter( + codec: _loadAsync(key, decodeBufferDeprecated: decode), scale: key.scale, debugLabel: 'MemoryImage(${describeIdentity(key.bytes)})', ); @@ -1576,10 +1720,20 @@ class MemoryImage extends ImageProvider { Future _loadAsync( MemoryImage key, { - required _SimpleDecoderCallback decode, + ImageDecoderCallback? decode, + DecoderBufferCallback? decodeBufferDeprecated, + DecoderCallback? decodeDeprecated, }) async { assert(key == this); - return decode(await ui.ImmutableBuffer.fromUint8List(bytes)); + if (decode != null) { + final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes); + return decode(buffer); + } + 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 f408d8835b..4009be91ed 100644 --- a/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart +++ b/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart @@ -63,7 +63,7 @@ class ScrollAwareImageProvider extends ImageProvider { /// been resolved. final DisposableBuildContext context; - /// The wrapped image provider to delegate [obtainKey] and [loadImage] to. + /// The wrapped image provider to delegate [obtainKey] and [load] to. final ImageProvider imageProvider; @override @@ -105,6 +105,9 @@ class ScrollAwareImageProvider extends ImageProvider { imageProvider.resolveStreamForKey(configuration, stream, key, handleError); } + @override + ImageStreamCompleter load(T key, DecoderCallback decode) => imageProvider.load(key, decode); + @override ImageStreamCompleter loadBuffer(T key, DecoderBufferCallback decode) => imageProvider.loadBuffer(key, decode); diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart index 0959ad2d2f..9fbf97f7ac 100644 --- a/packages/flutter/test/material/switch_test.dart +++ b/packages/flutter/test/material/switch_test.dart @@ -3556,7 +3556,7 @@ class DelayedImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(DelayedImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(DelayedImageProvider key, DecoderCallback decode) { return OneFrameImageStreamCompleter(_completer.future); } @@ -3592,7 +3592,7 @@ class _TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) { + ImageStreamCompleter load(Object key, DecoderCallback decode) { _loadCallCount += 1; return _streamCompleter; } diff --git a/packages/flutter/test/painting/decoration_test.dart b/packages/flutter/test/painting/decoration_test.dart index 6cfa461d82..8750ba5e48 100644 --- a/packages/flutter/test/painting/decoration_test.dart +++ b/packages/flutter/test/painting/decoration_test.dart @@ -34,7 +34,7 @@ class SynchronousTestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { + ImageStreamCompleter load(int key, DecoderCallback decode) { return OneFrameImageStreamCompleter( SynchronousFuture(TestImageInfo(key, image: image)), ); @@ -52,7 +52,7 @@ class SynchronousErrorTestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { + ImageStreamCompleter load(int key, DecoderCallback decode) { throw throwable; } } @@ -68,7 +68,7 @@ class AsyncTestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { + ImageStreamCompleter load(int key, DecoderCallback decode) { return OneFrameImageStreamCompleter( Future.value(TestImageInfo(key, image: image)), ); @@ -88,7 +88,7 @@ class DelayedImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(DelayedImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(DelayedImageProvider key, DecoderCallback decode) { return OneFrameImageStreamCompleter(_completer.future); } @@ -111,7 +111,7 @@ class MultiFrameImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(MultiFrameImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(MultiFrameImageProvider key, DecoderCallback decode) { return completer; } diff --git a/packages/flutter/test/painting/fake_image_provider.dart b/packages/flutter/test/painting/fake_image_provider.dart index a59f54670b..c352adaaab 100644 --- a/packages/flutter/test/painting/fake_image_provider.dart +++ b/packages/flutter/test/painting/fake_image_provider.dart @@ -25,7 +25,7 @@ class FakeImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(FakeImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(FakeImageProvider key, DecoderCallback decode) { assert(key == this); return MultiFrameImageStreamCompleter( codec: SynchronousFuture(_codec), diff --git a/packages/flutter/test/painting/image_test_utils.dart b/packages/flutter/test/painting/image_test_utils.dart index 4b137c3f34..847984663e 100644 --- a/packages/flutter/test/painting/image_test_utils.dart +++ b/packages/flutter/test/painting/image_test_utils.dart @@ -28,6 +28,11 @@ class TestImageProvider extends ImageProvider { super.resolveStreamForKey(config, stream, key, handleError); } + @override + ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) { + throw UnsupportedError('Use ImageProvider.loadImage instead.'); + } + @override ImageStreamCompleter loadBuffer(TestImageProvider key, DecoderBufferCallback decode) { throw UnsupportedError('Use ImageProvider.loadImage instead.'); diff --git a/packages/flutter/test/painting/mocks_for_image_cache.dart b/packages/flutter/test/painting/mocks_for_image_cache.dart index bc80315747..1273faa4c5 100644 --- a/packages/flutter/test/painting/mocks_for_image_cache.dart +++ b/packages/flutter/test/painting/mocks_for_image_cache.dart @@ -54,7 +54,7 @@ class TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { + ImageStreamCompleter load(int key, DecoderCallback decode) { return OneFrameImageStreamCompleter( SynchronousFuture(TestImageInfo(imageValue, image: image.clone())), ); @@ -68,7 +68,7 @@ class FailingTestImageProvider extends TestImageProvider { const FailingTestImageProvider(super.key, super.imageValue, { required super.image }); @override - ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { + ImageStreamCompleter load(int key, DecoderCallback decode) { return OneFrameImageStreamCompleter(Future.sync(() => Future.error('loading failed!'))); } } @@ -95,6 +95,11 @@ class ErrorImageProvider extends ImageProvider { throw Error(); } + @override + ImageStreamCompleter load(ErrorImageProvider key, DecoderCallback decode) { + throw Error(); + } + @override Future obtainKey(ImageConfiguration configuration) { return SynchronousFuture(this); @@ -116,6 +121,11 @@ class ObtainKeyErrorImageProvider extends ImageProvider obtainKey(ImageConfiguration configuration) { throw Error(); } + + @override + ImageStreamCompleter load(ObtainKeyErrorImageProvider key, DecoderCallback decode) { + throw UnimplementedError(); + } } class LoadErrorImageProvider extends ImageProvider { @@ -133,11 +143,16 @@ class LoadErrorImageProvider extends ImageProvider { Future obtainKey(ImageConfiguration configuration) { return SynchronousFuture(this); } + + @override + ImageStreamCompleter load(LoadErrorImageProvider key, DecoderCallback decode) { + throw UnimplementedError(); + } } class LoadErrorCompleterImageProvider extends ImageProvider { @override - ImageStreamCompleter loadImage(LoadErrorCompleterImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(LoadErrorCompleterImageProvider key, DecoderCallback decode) { final Completer completer = Completer.sync(); completer.completeError(Error()); return OneFrameImageStreamCompleter(completer.future); diff --git a/packages/flutter/test/painting/painting_utils.dart b/packages/flutter/test/painting/painting_utils.dart index 7d669fa1e3..b7edc0da12 100644 --- a/packages/flutter/test/painting/painting_utils.dart +++ b/packages/flutter/test/painting/painting_utils.dart @@ -14,9 +14,9 @@ class PaintingBindingSpy extends BindingBase with SchedulerBinding, ServicesBind int get instantiateImageCodecCalledCount => counter; @override - Future instantiateImageCodecWithSize(ui.ImmutableBuffer buffer, { ui.TargetImageSizeCallback? getTargetSize }) { + Future instantiateImageCodec(Uint8List list, {int? cacheWidth, int? cacheHeight, bool allowUpscaling = false}) { counter++; - return ui.instantiateImageCodecWithSize(buffer, getTargetSize: getTargetSize); + return ui.instantiateImageCodec(list); } @override diff --git a/packages/flutter/test/painting/shape_decoration_test.dart b/packages/flutter/test/painting/shape_decoration_test.dart index 269fb9e416..8a193a5faa 100644 --- a/packages/flutter/test/painting/shape_decoration_test.dart +++ b/packages/flutter/test/painting/shape_decoration_test.dart @@ -156,7 +156,7 @@ class TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(TestImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) { return OneFrameImageStreamCompleter( SynchronousFuture(ImageInfo(image: image)), ); diff --git a/packages/flutter/test/widgets/box_decoration_test.dart b/packages/flutter/test/widgets/box_decoration_test.dart index 031006439d..42f36c0657 100644 --- a/packages/flutter/test/widgets/box_decoration_test.dart +++ b/packages/flutter/test/widgets/box_decoration_test.dart @@ -25,7 +25,7 @@ class TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(TestImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) { return OneFrameImageStreamCompleter( future.then((void value) => ImageInfo(image: image)), ); diff --git a/packages/flutter/test/widgets/fade_in_image_test.dart b/packages/flutter/test/widgets/fade_in_image_test.dart index e88c6ca6e5..a10a77bd24 100644 --- a/packages/flutter/test/widgets/fade_in_image_test.dart +++ b/packages/flutter/test/widgets/fade_in_image_test.dart @@ -58,7 +58,7 @@ class LoadTestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) { + ImageStreamCompleter load(Object key, DecoderCallback decode) { throw UnimplementedError(); } } diff --git a/packages/flutter/test/widgets/image_filter_quality_test.dart b/packages/flutter/test/widgets/image_filter_quality_test.dart index dcbeadfd43..d8b1ee367b 100644 --- a/packages/flutter/test/widgets/image_filter_quality_test.dart +++ b/packages/flutter/test/widgets/image_filter_quality_test.dart @@ -137,7 +137,7 @@ class _TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) { + ImageStreamCompleter load(Object key, DecoderCallback decode) { _loadCallCount += 1; return _streamCompleter; } diff --git a/packages/flutter/test/widgets/image_rtl_test.dart b/packages/flutter/test/widgets/image_rtl_test.dart index 6f2c075a00..2fb1aa6877 100644 --- a/packages/flutter/test/widgets/image_rtl_test.dart +++ b/packages/flutter/test/widgets/image_rtl_test.dart @@ -19,7 +19,7 @@ class TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(TestImageProvider key, ImageDecoderCallback decode) { + ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) { return OneFrameImageStreamCompleter( SynchronousFuture(ImageInfo(image: image)), ); diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index cbabca138f..2eb4b80b64 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -2083,7 +2083,7 @@ class _TestImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) { + ImageStreamCompleter load(Object key, DecoderCallback decode) { _loadCallCount += 1; return _streamCompleter; } @@ -2198,7 +2198,7 @@ class _FailingImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage(int key, ImageDecoderCallback decode) { + ImageStreamCompleter load(int key, DecoderCallback decode) { if (failOnLoad) { throw throws; }