From d3a66e310732be89795b1200f3c867386ded4271 Mon Sep 17 00:00:00 2001 From: Ferhat Date: Tue, 17 Mar 2020 16:07:21 -0700 Subject: [PATCH] [web] Add support for ChunkEvents during image loading (#52558) * Add support for ChunkEvents for web * Add lint skip for webOnly call in _network_image_web --- .../lib/src/painting/_network_image_web.dart | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/packages/flutter/lib/src/painting/_network_image_web.dart b/packages/flutter/lib/src/painting/_network_image_web.dart index 8641e213930..2e9771b50f7 100644 --- a/packages/flutter/lib/src/painting/_network_image_web.dart +++ b/packages/flutter/lib/src/painting/_network_image_web.dart @@ -13,7 +13,9 @@ import 'image_stream.dart'; /// The dart:html implementation of [image_provider.NetworkImage]. /// /// NetworkImage on the web does not support decoding to a specified size. -class NetworkImage extends image_provider.ImageProvider implements image_provider.NetworkImage { +class NetworkImage + extends image_provider.ImageProvider + implements image_provider.NetworkImage { /// Creates an object that fetches the image at the given URL. /// /// The arguments [url] and [scale] must not be null. @@ -31,22 +33,41 @@ class NetworkImage extends image_provider.ImageProvider headers; @override - Future obtainKey(image_provider.ImageConfiguration configuration) { + Future obtainKey( + image_provider.ImageConfiguration configuration) { return SynchronousFuture(this); } @override - ImageStreamCompleter load(image_provider.NetworkImage key, image_provider.DecoderCallback decode) { + 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, decode), - scale: key.scale, - informationCollector: () { + chunkEvents: chunkEvents.stream, + codec: _loadAsync(key as NetworkImage, decode, chunkEvents), + scale: key.scale, + informationCollector: _imageStreamInformationCollector(key)); + } + + InformationCollector _imageStreamInformationCollector( + image_provider.NetworkImage key) { + InformationCollector collector; + assert(() { + collector = () { return [ - DiagnosticsProperty('Image provider', this), + DiagnosticsProperty( + 'Image provider', this), DiagnosticsProperty('Image key', key as NetworkImage), ]; - }, - ); + }; + return true; + }()); + return collector; } // TODO(garyq): We should eventually support custom decoding of network images on Web as @@ -55,13 +76,20 @@ class NetworkImage extends image_provider.ImageProvider _loadAsync(NetworkImage key, image_provider.DecoderCallback decode) { + Future _loadAsync( + NetworkImage key, + image_provider.DecoderCallback decode, + StreamController chunkEvents) { assert(key == this); final Uri resolved = Uri.base.resolve(key.url); // This API only exists in the web engine implementation and is not // contained in the analyzer summary for Flutter. - return ui.webOnlyInstantiateImageCodecFromUrl(resolved) as Future; // ignore: undefined_function + return ui.webOnlyInstantiateImageCodecFromUrl(resolved, // ignore: undefined_function + chunkCallback: (int bytes, int total) { + chunkEvents.add(ImageChunkEvent( + cumulativeBytesLoaded: bytes, expectedTotalBytes: total)); + }) as Future; // ignore: undefined_function } @override @@ -69,14 +97,13 @@ class NetworkImage extends image_provider.ImageProvider ui.hashValues(url, scale); @override - String toString() => '${objectRuntimeType(this, 'NetworkImage')}("$url", scale: $scale)'; + String toString() => + '${objectRuntimeType(this, 'NetworkImage')}("$url", scale: $scale)'; }