Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8d2978af
Unverified
Commit
8d2978af
authored
May 27, 2022
by
Jonah Williams
Committed by
GitHub
May 27, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use immutable buffer for loading asset images (#103496)
parent
5cb9c219
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
368 additions
and
74 deletions
+368
-74
animated_placeholder.dart
...chmarks/macrobenchmarks/lib/src/animated_placeholder.dart
+3
-2
image_bench.dart
dev/benchmarks/microbenchmarks/lib/ui/image_bench.dart
+1
-3
_network_image_io.dart
packages/flutter/lib/src/painting/_network_image_io.dart
+29
-3
_network_image_web.dart
packages/flutter/lib/src/painting/_network_image_web.dart
+27
-3
binding.dart
packages/flutter/lib/src/painting/binding.dart
+46
-1
image_provider.dart
packages/flutter/lib/src/painting/image_provider.dart
+150
-22
asset_bundle.dart
packages/flutter/lib/src/services/asset_bundle.dart
+29
-1
scroll_aware_image_provider.dart
.../flutter/lib/src/widgets/scroll_aware_image_provider.dart
+3
-0
image_cache_test.dart
packages/flutter/test/painting/image_cache_test.dart
+4
-5
image_provider_and_image_cache_test.dart
...er/test/painting/image_provider_and_image_cache_test.dart
+3
-3
image_provider_network_image_test.dart
...tter/test/painting/image_provider_network_image_test.dart
+6
-6
image_provider_resize_image_test.dart
...utter/test/painting/image_provider_resize_image_test.dart
+3
-3
image_provider_test.dart
packages/flutter/test/painting/image_provider_test.dart
+6
-6
image_resolution_test.dart
packages/flutter/test/painting/image_resolution_test.dart
+7
-0
image_test_utils.dart
packages/flutter/test/painting/image_test_utils.dart
+5
-0
mocks_for_image_cache.dart
packages/flutter/test/painting/mocks_for_image_cache.dart
+17
-2
fade_in_image_test.dart
packages/flutter/test/widgets/fade_in_image_test.dart
+25
-10
image_resolution_test.dart
packages/flutter/test/widgets/image_resolution_test.dart
+1
-1
image_test.dart
packages/flutter/test/widgets/image_test.dart
+1
-1
scroll_aware_image_provider_test.dart
...lutter/test/widgets/scroll_aware_image_provider_test.dart
+2
-2
No files found.
dev/benchmarks/macrobenchmarks/lib/src/animated_placeholder.dart
View file @
8d2978af
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:ui'
as
ui
show
Codec
;
import
'dart:ui'
as
ui
show
Codec
;
import
'dart:ui'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
...
@@ -57,11 +58,11 @@ class DelayedBase64Image extends ImageProvider<int> {
...
@@ -57,11 +58,11 @@ class DelayedBase64Image extends ImageProvider<int> {
}
}
@override
@override
ImageStreamCompleter
load
(
int
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
int
key
,
DecoderBuff
erCallback
decode
)
{
return
MultiFrameImageStreamCompleter
(
return
MultiFrameImageStreamCompleter
(
codec:
Future
<
ui
.
Codec
>.
delayed
(
codec:
Future
<
ui
.
Codec
>.
delayed
(
delay
,
delay
,
()
=>
decode
(
base64
.
decode
(
data
)),
()
async
=>
decode
(
await
ImmutableBuffer
.
fromUint8List
(
base64
.
decode
(
data
)
)),
),
),
scale:
1.0
,
scale:
1.0
,
);
);
...
...
dev/benchmarks/microbenchmarks/lib/ui/image_bench.dart
View file @
8d2978af
...
@@ -87,9 +87,7 @@ Future<void> main() async {
...
@@ -87,9 +87,7 @@ Future<void> main() async {
for
(
int
i
=
0
;
i
<
10
;
i
+=
1
)
{
for
(
int
i
=
0
;
i
<
10
;
i
+=
1
)
{
await
Future
.
wait
(<
Future
<
ui
.
ImmutableBuffer
>>[
await
Future
.
wait
(<
Future
<
ui
.
ImmutableBuffer
>>[
for
(
String
asset
in
assets
)
for
(
String
asset
in
assets
)
rootBundle
.
load
(
asset
).
then
((
ByteData
data
)
{
rootBundle
.
loadBuffer
(
asset
)
return
ui
.
ImmutableBuffer
.
fromUint8List
(
data
.
buffer
.
asUint8List
());
})
]);
]);
}
}
watch
.
stop
();
watch
.
stop
();
...
...
packages/flutter/lib/src/painting/_network_image_io.dart
View file @
8d2978af
...
@@ -46,7 +46,26 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
...
@@ -46,7 +46,26 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
final
StreamController
<
ImageChunkEvent
>
chunkEvents
=
StreamController
<
ImageChunkEvent
>();
final
StreamController
<
ImageChunkEvent
>
chunkEvents
=
StreamController
<
ImageChunkEvent
>();
return
MultiFrameImageStreamCompleter
(
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
as
NetworkImage
,
chunkEvents
,
decode
),
codec:
_loadAsync
(
key
as
NetworkImage
,
chunkEvents
,
null
,
decode
),
chunkEvents:
chunkEvents
.
stream
,
scale:
key
.
scale
,
debugLabel:
key
.
url
,
informationCollector:
()
=>
<
DiagnosticsNode
>[
DiagnosticsProperty
<
image_provider
.
ImageProvider
>(
'Image provider'
,
this
),
DiagnosticsProperty
<
image_provider
.
NetworkImage
>(
'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
// method's responsibility to close the controller's stream when the image
// has been loaded or an error is thrown.
final
StreamController
<
ImageChunkEvent
>
chunkEvents
=
StreamController
<
ImageChunkEvent
>();
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
as
NetworkImage
,
chunkEvents
,
decode
,
null
),
chunkEvents:
chunkEvents
.
stream
,
chunkEvents:
chunkEvents
.
stream
,
scale:
key
.
scale
,
scale:
key
.
scale
,
debugLabel:
key
.
url
,
debugLabel:
key
.
url
,
...
@@ -77,7 +96,8 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
...
@@ -77,7 +96,8 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
Future
<
ui
.
Codec
>
_loadAsync
(
Future
<
ui
.
Codec
>
_loadAsync
(
NetworkImage
key
,
NetworkImage
key
,
StreamController
<
ImageChunkEvent
>
chunkEvents
,
StreamController
<
ImageChunkEvent
>
chunkEvents
,
image_provider
.
DecoderCallback
decode
,
image_provider
.
DecoderBufferCallback
?
decode
,
image_provider
.
DecoderCallback
?
decodeDepreacted
,
)
async
{
)
async
{
try
{
try
{
assert
(
key
==
this
);
assert
(
key
==
this
);
...
@@ -111,7 +131,13 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
...
@@ -111,7 +131,13 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
throw
Exception
(
'NetworkImage is an empty file:
$resolved
'
);
throw
Exception
(
'NetworkImage is an empty file:
$resolved
'
);
}
}
return
decode
(
bytes
);
if
(
decode
!=
null
)
{
final
ui
.
ImmutableBuffer
buffer
=
await
ui
.
ImmutableBuffer
.
fromUint8List
(
bytes
);
return
decode
(
buffer
);
}
else
{
assert
(
decodeDepreacted
!=
null
);
return
decodeDepreacted
!(
bytes
);
}
}
catch
(
e
)
{
}
catch
(
e
)
{
// Depending on where the exception was thrown, the image cache may not
// Depending on where the exception was thrown, the image cache may not
// have had a chance to track the key in the cache at all.
// have had a chance to track the key in the cache at all.
...
...
packages/flutter/lib/src/painting/_network_image_web.dart
View file @
8d2978af
...
@@ -66,7 +66,24 @@ class NetworkImage
...
@@ -66,7 +66,24 @@ class NetworkImage
return
MultiFrameImageStreamCompleter
(
return
MultiFrameImageStreamCompleter
(
chunkEvents:
chunkEvents
.
stream
,
chunkEvents:
chunkEvents
.
stream
,
codec:
_loadAsync
(
key
as
NetworkImage
,
decode
,
chunkEvents
),
codec:
_loadAsync
(
key
as
NetworkImage
,
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
// method's responsibility to close the controller's stream when the image
// has been loaded or an error is thrown.
final
StreamController
<
ImageChunkEvent
>
chunkEvents
=
StreamController
<
ImageChunkEvent
>();
return
MultiFrameImageStreamCompleter
(
chunkEvents:
chunkEvents
.
stream
,
codec:
_loadAsync
(
key
as
NetworkImage
,
decode
,
null
,
chunkEvents
),
scale:
key
.
scale
,
scale:
key
.
scale
,
debugLabel:
key
.
url
,
debugLabel:
key
.
url
,
informationCollector:
_imageStreamInformationCollector
(
key
),
informationCollector:
_imageStreamInformationCollector
(
key
),
...
@@ -93,7 +110,8 @@ class NetworkImage
...
@@ -93,7 +110,8 @@ class NetworkImage
// directly in place of the typical `instantiateImageCodec` method.
// directly in place of the typical `instantiateImageCodec` method.
Future
<
ui
.
Codec
>
_loadAsync
(
Future
<
ui
.
Codec
>
_loadAsync
(
NetworkImage
key
,
NetworkImage
key
,
image_provider
.
DecoderCallback
decode
,
image_provider
.
DecoderBufferCallback
?
decode
,
image_provider
.
DecoderCallback
?
decodeDepreacted
,
StreamController
<
ImageChunkEvent
>
chunkEvents
,
StreamController
<
ImageChunkEvent
>
chunkEvents
,
)
async
{
)
async
{
assert
(
key
==
this
);
assert
(
key
==
this
);
...
@@ -144,7 +162,13 @@ class NetworkImage
...
@@ -144,7 +162,13 @@ class NetworkImage
statusCode:
request
.
status
!,
uri:
resolved
);
statusCode:
request
.
status
!,
uri:
resolved
);
}
}
return
decode
(
bytes
);
if
(
decode
!=
null
)
{
final
ui
.
ImmutableBuffer
buffer
=
await
ui
.
ImmutableBuffer
.
fromUint8List
(
bytes
);
return
decode
(
buffer
);
}
else
{
assert
(
decodeDepreacted
!=
null
);
return
decodeDepreacted
!(
bytes
);
}
}
else
{
}
else
{
// This API only exists in the web engine implementation and is not
// This API only exists in the web engine implementation and is not
// contained in the analyzer summary for Flutter.
// contained in the analyzer summary for Flutter.
...
...
packages/flutter/lib/src/painting/binding.dart
View file @
8d2978af
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:typed_data'
show
Uint8List
;
import
'dart:typed_data'
show
Uint8List
;
import
'dart:ui'
as
ui
show
instantiateImageCodec
,
Codec
;
import
'dart:ui'
as
ui
show
instantiateImageCodec
,
instantiateImageCodecFromBuffer
,
Codec
,
ImmutableBuffer
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/services.dart'
show
ServicesBinding
;
import
'package:flutter/services.dart'
show
ServicesBinding
;
...
@@ -81,6 +81,9 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
...
@@ -81,6 +81,9 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// Calls through to [dart:ui.instantiateImageCodec] from [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 `cacheWidth` and `cacheHeight` parameters, when specified, indicate
/// the size to decode the image to.
/// the size to decode the image to.
///
///
...
@@ -97,6 +100,10 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
...
@@ -97,6 +100,10 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// unnecessary memory usage for images. Callers that wish to display an image
/// unnecessary memory usage for images. Callers that wish to display an image
/// above its native resolution should prefer scaling the canvas the image is
/// above its native resolution should prefer scaling the canvas the image is
/// drawn into.
/// drawn into.
@Deprecated
(
'Use instantiateImageCodecFromBuffer with an ImmutableBuffer instance instead. '
'This feature was deprecated after v2.13.0-1.0.pre.'
,
)
Future
<
ui
.
Codec
>
instantiateImageCodec
(
Future
<
ui
.
Codec
>
instantiateImageCodec
(
Uint8List
bytes
,
{
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheWidth
,
...
@@ -114,6 +121,44 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
...
@@ -114,6 +121,44 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
);
);
}
}
/// Calls through to [dart:ui.instantiateImageCodecFromBuffer] from [ImageCache].
///
/// The [buffer] parameter should be an [ui.ImmutableBuffer] instance which can
/// be acquired from [ui.ImmutableBuffer.fromUint8List] or [ui.ImmutableBuffer.fromAsset].
///
/// 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.
Future
<
ui
.
Codec
>
instantiateImageCodecFromBuffer
(
ui
.
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
,
})
{
assert
(
cacheWidth
==
null
||
cacheWidth
>
0
);
assert
(
cacheHeight
==
null
||
cacheHeight
>
0
);
assert
(
allowUpscaling
!=
null
);
return
ui
.
instantiateImageCodecFromBuffer
(
buffer
,
targetWidth:
cacheWidth
,
targetHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
,
);
}
@override
@override
void
evict
(
String
asset
)
{
void
evict
(
String
asset
)
{
super
.
evict
(
asset
);
super
.
evict
(
asset
);
...
...
packages/flutter/lib/src/painting/image_provider.dart
View file @
8d2978af
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
import
'dart:async'
;
import
'dart:async'
;
import
'dart:io'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
show
Codec
;
import
'dart:ui'
as
ui
show
Codec
,
ImmutableBuffer
;
import
'dart:ui'
show
Size
,
Locale
,
TextDirection
;
import
'dart:ui'
show
Size
,
Locale
,
TextDirection
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
...
@@ -164,6 +164,26 @@ class ImageConfiguration {
...
@@ -164,6 +164,26 @@ class ImageConfiguration {
/// Performs the decode process for use in [ImageProvider.load].
/// Performs the decode process for use in [ImageProvider.load].
///
///
/// This typedef is deprecated. Use [DecoderBufferCallback] with
/// [ImageProvider.loadBuffer] 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 DecoderBufferCallback with ImageProvider.loadBuffer instead. '
'This feature was deprecated after v2.13.0-1.0.pre.'
,
)
typedef
DecoderCallback
=
Future
<
ui
.
Codec
>
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
/// This callback allows decoupling of the `cacheWidth`, `cacheHeight`, and
/// `allowUpscaling` parameters from implementations of [ImageProvider] that do
/// `allowUpscaling` parameters from implementations of [ImageProvider] that do
/// not expose them.
/// not expose them.
...
@@ -172,7 +192,7 @@ class ImageConfiguration {
...
@@ -172,7 +192,7 @@ class ImageConfiguration {
///
///
/// * [ResizeImage], which uses this to override the `cacheWidth`,
/// * [ResizeImage], which uses this to override the `cacheWidth`,
/// `cacheHeight`, and `allowUpscaling` parameters.
/// `cacheHeight`, and `allowUpscaling` parameters.
typedef
Decoder
Callback
=
Future
<
ui
.
Codec
>
Function
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
});
typedef
Decoder
BufferCallback
=
Future
<
ui
.
Codec
>
Function
(
ui
.
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
});
/// Identifies an image without committing to the precise final asset. This
/// 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
/// allows a set of images to be identified and for the precise image to later
...
@@ -213,16 +233,16 @@ typedef DecoderCallback = Future<ui.Codec> Function(Uint8List bytes, {int? cache
...
@@ -213,16 +233,16 @@ typedef DecoderCallback = Future<ui.Codec> Function(Uint8List bytes, {int? cache
/// using that key. This is handled by [resolveStreamForKey]. That method
/// using that key. This is handled by [resolveStreamForKey]. That method
/// may fizzle if it determines the image is no longer necessary, use the
/// may fizzle if it determines the image is no longer necessary, use the
/// provided [ImageErrorListener] to report an error, set the completer
/// provided [ImageErrorListener] to report an error, set the completer
/// from the cache if possible, or call [load] to fetch the encoded image
/// from the cache if possible, or call [load
Buffer
] to fetch the encoded image
/// bytes and schedule decoding.
/// bytes and schedule decoding.
/// 4. The [load] method is responsible for both fetching the encoded bytes
/// 4. The [load
Buffer
] method is responsible for both fetching the encoded bytes
/// and decoding them using the provided [DecoderCallback]. It is called
/// and decoding them using the provided [DecoderCallback]. It is called
/// in a context that uses the [ImageErrorListener] to report errors back.
/// in a context that uses the [ImageErrorListener] to report errors back.
///
///
/// Subclasses normally only have to implement the [load] and [obtainKey]
/// Subclasses normally only have to implement the [load
Buffer
] and [obtainKey]
/// methods. A subclass that needs finer grained control over the [ImageStream]
/// methods. A subclass that needs finer grained control over the [ImageStream]
/// type must override [createStream]. A subclass that needs finer grained
/// type must override [createStream]. A subclass that needs finer grained
/// control over the resolution, such as delaying calling [load], must override
/// control over the resolution, such as delaying calling [load
Buffer
], must override
/// [resolveStreamForKey].
/// [resolveStreamForKey].
///
///
/// The [resolve] method is marked as [nonVirtual] so that [ImageProvider]s can
/// The [resolve] method is marked as [nonVirtual] so that [ImageProvider]s can
...
@@ -491,7 +511,7 @@ abstract class ImageProvider<T extends Object> {
...
@@ -491,7 +511,7 @@ abstract class ImageProvider<T extends Object> {
}
}
final
ImageStreamCompleter
?
completer
=
PaintingBinding
.
instance
.
imageCache
.
putIfAbsent
(
final
ImageStreamCompleter
?
completer
=
PaintingBinding
.
instance
.
imageCache
.
putIfAbsent
(
key
,
key
,
()
=>
load
(
key
,
PaintingBinding
.
instance
.
instantiateImageCodec
),
()
=>
load
Buffer
(
key
,
PaintingBinding
.
instance
.
instantiateImageCodecFromBuffer
),
onError:
handleError
,
onError:
handleError
,
);
);
if
(
completer
!=
null
)
{
if
(
completer
!=
null
)
{
...
@@ -563,6 +583,10 @@ abstract class ImageProvider<T extends Object> {
...
@@ -563,6 +583,10 @@ abstract class ImageProvider<T extends Object> {
/// Converts a key into an [ImageStreamCompleter], and begins fetching the
/// Converts a key into an [ImageStreamCompleter], and begins fetching the
/// image.
/// image.
///
///
/// This method is deprecated. Implement [loadBuffer] for faster image
/// loading. Only one of [load] and [loadBuffer] must be implemented, and
/// [loadBuffer] is preferred.
///
/// The [decode] callback provides the logic to obtain the codec for the
/// The [decode] callback provides the logic to obtain the codec for the
/// image.
/// image.
///
///
...
@@ -570,7 +594,31 @@ abstract class ImageProvider<T extends Object> {
...
@@ -570,7 +594,31 @@ abstract class ImageProvider<T extends Object> {
///
///
/// * [ResizeImage], for modifying the key to account for cache dimensions.
/// * [ResizeImage], for modifying the key to account for cache dimensions.
@protected
@protected
ImageStreamCompleter
load
(
T
key
,
DecoderCallback
decode
);
@Deprecated
(
'Implement loadBuffer for faster image loading. '
'This feature was deprecated after v2.13.0-1.0.pre.'
,
)
ImageStreamCompleter
load
(
T
key
,
DecoderCallback
decode
)
{
throw
UnsupportedError
(
'Implement loadBuffer for faster image loading'
);
}
/// 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.
///
/// 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
ImageStreamCompleter
loadBuffer
(
T
key
,
DecoderBufferCallback
decode
)
{
return
load
(
key
,
PaintingBinding
.
instance
.
instantiateImageCodec
);
}
@override
@override
String
toString
()
=>
'
${objectRuntimeType(this, 'ImageConfiguration')}
()'
;
String
toString
()
=>
'
${objectRuntimeType(this, 'ImageConfiguration')}
()'
;
...
@@ -634,6 +682,24 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
...
@@ -634,6 +682,24 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
/// Converts a key into an [ImageStreamCompleter], and begins fetching the
/// Converts a key into an [ImageStreamCompleter], and begins fetching the
/// image.
/// image.
@override
ImageStreamCompleter
loadBuffer
(
AssetBundleImageKey
key
,
DecoderBufferCallback
decode
)
{
InformationCollector
?
collector
;
assert
(()
{
collector
=
()
=>
<
DiagnosticsNode
>[
DiagnosticsProperty
<
ImageProvider
>(
'Image provider'
,
this
),
DiagnosticsProperty
<
AssetBundleImageKey
>(
'Image key'
,
key
),
];
return
true
;
}());
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
,
decode
,
null
),
scale:
key
.
scale
,
debugLabel:
key
.
name
,
informationCollector:
collector
,
);
}
@override
@override
ImageStreamCompleter
load
(
AssetBundleImageKey
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
AssetBundleImageKey
key
,
DecoderCallback
decode
)
{
InformationCollector
?
collector
;
InformationCollector
?
collector
;
...
@@ -645,7 +711,7 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
...
@@ -645,7 +711,7 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
return
true
;
return
true
;
}());
}());
return
MultiFrameImageStreamCompleter
(
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
,
decode
),
codec:
_loadAsync
(
key
,
null
,
decode
),
scale:
key
.
scale
,
scale:
key
.
scale
,
debugLabel:
key
.
name
,
debugLabel:
key
.
name
,
informationCollector:
collector
,
informationCollector:
collector
,
...
@@ -657,8 +723,24 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
...
@@ -657,8 +723,24 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
///
///
/// This function is used by [load].
/// This function is used by [load].
@protected
@protected
Future
<
ui
.
Codec
>
_loadAsync
(
AssetBundleImageKey
key
,
DecoderCallback
decode
)
async
{
Future
<
ui
.
Codec
>
_loadAsync
(
AssetBundleImageKey
key
,
DecoderBufferCallback
?
decode
,
DecoderCallback
?
decodeDepreacted
)
async
{
ByteData
?
data
;
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
;
}
if
(
buffer
==
null
)
{
PaintingBinding
.
instance
.
imageCache
.
evict
(
key
);
throw
StateError
(
'Unable to read data'
);
}
return
decode
(
buffer
);
}
ByteData
data
;
// Hot reload/restart could change whether an asset bundle or key in a
// Hot reload/restart could change whether an asset bundle or key in a
// bundle are available, or if it is a network backed bundle.
// bundle are available, or if it is a network backed bundle.
try
{
try
{
...
@@ -671,7 +753,7 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
...
@@ -671,7 +753,7 @@ abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKe
PaintingBinding
.
instance
.
imageCache
.
evict
(
key
);
PaintingBinding
.
instance
.
imageCache
.
evict
(
key
);
throw
StateError
(
'Unable to read data'
);
throw
StateError
(
'Unable to read data'
);
}
}
return
decode
(
data
.
buffer
.
asUint8List
());
return
decode
Depreacted
!
(
data
.
buffer
.
asUint8List
());
}
}
}
}
...
@@ -757,13 +839,13 @@ class ResizeImage extends ImageProvider<ResizeImageKey> {
...
@@ -757,13 +839,13 @@ class ResizeImage extends ImageProvider<ResizeImageKey> {
@override
@override
ImageStreamCompleter
load
(
ResizeImageKey
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
ResizeImageKey
key
,
DecoderCallback
decode
)
{
Future
<
ui
.
Codec
>
decodeResize
(
Uint8List
b
ytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
Future
<
ui
.
Codec
>
decodeResize
(
Uint8List
b
uffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
assert
(
assert
(
cacheWidth
==
null
&&
cacheHeight
==
null
&&
allowUpscaling
==
null
,
cacheWidth
==
null
&&
cacheHeight
==
null
&&
allowUpscaling
==
null
,
'ResizeImage cannot be composed with another ImageProvider that applies '
'ResizeImage cannot be composed with another ImageProvider that applies '
'cacheWidth, cacheHeight, or allowUpscaling.'
,
'cacheWidth, cacheHeight, or allowUpscaling.'
,
);
);
return
decode
(
b
ytes
,
cacheWidth:
width
,
cacheHeight:
height
,
allowUpscaling:
this
.
allowUpscaling
);
return
decode
(
b
uffer
,
cacheWidth:
width
,
cacheHeight:
height
,
allowUpscaling:
this
.
allowUpscaling
);
}
}
final
ImageStreamCompleter
completer
=
imageProvider
.
load
(
key
.
_providerCacheKey
,
decodeResize
);
final
ImageStreamCompleter
completer
=
imageProvider
.
load
(
key
.
_providerCacheKey
,
decodeResize
);
if
(!
kReleaseMode
)
{
if
(!
kReleaseMode
)
{
...
@@ -772,6 +854,23 @@ class ResizeImage extends ImageProvider<ResizeImageKey> {
...
@@ -772,6 +854,23 @@ class ResizeImage extends ImageProvider<ResizeImageKey> {
return
completer
;
return
completer
;
}
}
@override
ImageStreamCompleter
loadBuffer
(
ResizeImageKey
key
,
DecoderBufferCallback
decode
)
{
Future
<
ui
.
Codec
>
decodeResize
(
ui
.
ImmutableBuffer
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
.
loadBuffer
(
key
.
_providerCacheKey
,
decodeResize
);
if
(!
kReleaseMode
)
{
completer
.
debugLabel
=
'
${completer.debugLabel}
- Resized(
${key._width}
×
${key._height}
)'
;
}
return
completer
;
}
@override
@override
Future
<
ResizeImageKey
>
obtainKey
(
ImageConfiguration
configuration
)
{
Future
<
ResizeImageKey
>
obtainKey
(
ImageConfiguration
configuration
)
{
Completer
<
ResizeImageKey
>?
completer
;
Completer
<
ResizeImageKey
>?
completer
;
...
@@ -832,6 +931,9 @@ abstract class NetworkImage extends ImageProvider<NetworkImage> {
...
@@ -832,6 +931,9 @@ abstract class NetworkImage extends ImageProvider<NetworkImage> {
@override
@override
ImageStreamCompleter
load
(
NetworkImage
key
,
DecoderCallback
decode
);
ImageStreamCompleter
load
(
NetworkImage
key
,
DecoderCallback
decode
);
@override
ImageStreamCompleter
loadBuffer
(
NetworkImage
key
,
DecoderBufferCallback
decode
);
}
}
/// Decodes the given [File] object as an image, associating it with the given
/// Decodes the given [File] object as an image, associating it with the given
...
@@ -866,7 +968,19 @@ class FileImage extends ImageProvider<FileImage> {
...
@@ -866,7 +968,19 @@ class FileImage extends ImageProvider<FileImage> {
@override
@override
ImageStreamCompleter
load
(
FileImage
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
FileImage
key
,
DecoderCallback
decode
)
{
return
MultiFrameImageStreamCompleter
(
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
,
decode
),
codec:
_loadAsync
(
key
,
null
,
decode
),
scale:
key
.
scale
,
debugLabel:
key
.
file
.
path
,
informationCollector:
()
=>
<
DiagnosticsNode
>[
ErrorDescription
(
'Path:
${file.path}
'
),
],
);
}
@override
ImageStreamCompleter
loadBuffer
(
FileImage
key
,
DecoderBufferCallback
decode
)
{
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
,
decode
,
null
),
scale:
key
.
scale
,
scale:
key
.
scale
,
debugLabel:
key
.
file
.
path
,
debugLabel:
key
.
file
.
path
,
informationCollector:
()
=>
<
DiagnosticsNode
>[
informationCollector:
()
=>
<
DiagnosticsNode
>[
...
@@ -875,18 +989,20 @@ class FileImage extends ImageProvider<FileImage> {
...
@@ -875,18 +989,20 @@ class FileImage extends ImageProvider<FileImage> {
);
);
}
}
Future
<
ui
.
Codec
>
_loadAsync
(
FileImage
key
,
Decoder
Callback
decode
)
async
{
Future
<
ui
.
Codec
>
_loadAsync
(
FileImage
key
,
Decoder
BufferCallback
?
decode
,
DecoderCallback
?
decodeDeprecated
)
async
{
assert
(
key
==
this
);
assert
(
key
==
this
);
final
Uint8List
bytes
=
await
file
.
readAsBytes
();
final
Uint8List
bytes
=
await
file
.
readAsBytes
();
if
(
bytes
.
lengthInBytes
==
0
)
{
if
(
bytes
.
lengthInBytes
==
0
)
{
// The file may become available later.
// The file may become available later.
PaintingBinding
.
instance
.
imageCache
.
evict
(
key
);
PaintingBinding
.
instance
.
imageCache
.
evict
(
key
);
throw
StateError
(
'
$file
is empty and cannot be loaded as an image.'
);
throw
StateError
(
'
$file
is empty and cannot be loaded as an image.'
);
}
}
return
decode
(
bytes
);
if
(
decode
!=
null
)
{
return
decode
(
await
ui
.
ImmutableBuffer
.
fromUint8List
(
bytes
));
}
return
decodeDeprecated
!(
bytes
);
}
}
@override
@override
...
@@ -953,16 +1069,28 @@ class MemoryImage extends ImageProvider<MemoryImage> {
...
@@ -953,16 +1069,28 @@ class MemoryImage extends ImageProvider<MemoryImage> {
@override
@override
ImageStreamCompleter
load
(
MemoryImage
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
MemoryImage
key
,
DecoderCallback
decode
)
{
return
MultiFrameImageStreamCompleter
(
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
,
decode
),
codec:
_loadAsync
(
key
,
null
,
decode
),
scale:
key
.
scale
,
scale:
key
.
scale
,
debugLabel:
'MemoryImage(
${describeIdentity(key.bytes)}
)'
,
debugLabel:
'MemoryImage(
${describeIdentity(key.bytes)}
)'
,
);
);
}
}
Future
<
ui
.
Codec
>
_loadAsync
(
MemoryImage
key
,
DecoderCallback
decode
)
{
@override
assert
(
key
==
this
);
ImageStreamCompleter
loadBuffer
(
MemoryImage
key
,
DecoderBufferCallback
decode
)
{
return
MultiFrameImageStreamCompleter
(
codec:
_loadAsync
(
key
,
decode
,
null
),
scale:
key
.
scale
,
debugLabel:
'MemoryImage(
${describeIdentity(key.bytes)}
)'
,
);
}
return
decode
(
bytes
);
Future
<
ui
.
Codec
>
_loadAsync
(
MemoryImage
key
,
DecoderBufferCallback
?
decode
,
DecoderCallback
?
decodeDepreacted
)
async
{
assert
(
key
==
this
);
if
(
decode
!=
null
)
{
final
ui
.
ImmutableBuffer
buffer
=
await
ui
.
ImmutableBuffer
.
fromUint8List
(
bytes
);
return
decode
(
buffer
);
}
return
decodeDepreacted
!(
bytes
);
}
}
@override
@override
...
...
packages/flutter/lib/src/services/asset_bundle.dart
View file @
8d2978af
...
@@ -2,11 +2,11 @@
...
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
...
@@ -55,6 +55,15 @@ abstract class AssetBundle {
...
@@ -55,6 +55,15 @@ abstract class AssetBundle {
/// Throws an exception if the asset is not found.
/// Throws an exception if the asset is not found.
Future
<
ByteData
>
load
(
String
key
);
Future
<
ByteData
>
load
(
String
key
);
/// Retrieve a binary resource from the asset bundle as an immutable
/// buffer.
///
/// Throws an exception if the asset is not found.
Future
<
ui
.
ImmutableBuffer
>
loadBuffer
(
String
key
)
async
{
final
ByteData
data
=
await
load
(
key
);
return
ui
.
ImmutableBuffer
.
fromUint8List
(
data
.
buffer
.
asUint8List
());
}
/// Retrieve a string from the asset bundle.
/// Retrieve a string from the asset bundle.
///
///
/// Throws an exception if the asset is not found.
/// Throws an exception if the asset is not found.
...
@@ -228,6 +237,12 @@ abstract class CachingAssetBundle extends AssetBundle {
...
@@ -228,6 +237,12 @@ abstract class CachingAssetBundle extends AssetBundle {
_stringCache
.
clear
();
_stringCache
.
clear
();
_structuredDataCache
.
clear
();
_structuredDataCache
.
clear
();
}
}
@override
Future
<
ui
.
ImmutableBuffer
>
loadBuffer
(
String
key
)
async
{
final
ByteData
data
=
await
load
(
key
);
return
ui
.
ImmutableBuffer
.
fromUint8List
(
data
.
buffer
.
asUint8List
());
}
}
}
/// An [AssetBundle] that loads resources using platform messages.
/// An [AssetBundle] that loads resources using platform messages.
...
@@ -242,6 +257,19 @@ class PlatformAssetBundle extends CachingAssetBundle {
...
@@ -242,6 +257,19 @@ class PlatformAssetBundle extends CachingAssetBundle {
}
}
return
asset
;
return
asset
;
}
}
@override
Future
<
ui
.
ImmutableBuffer
>
loadBuffer
(
String
key
)
async
{
if
(
kIsWeb
)
{
final
ByteData
bytes
=
await
load
(
key
);
return
ui
.
ImmutableBuffer
.
fromUint8List
(
bytes
.
buffer
.
asUint8List
());
}
try
{
return
await
ui
.
ImmutableBuffer
.
fromAsset
(
key
);
}
on
Exception
{
throw
FlutterError
(
'Unable to load asset:
$key
.'
);
}
}
}
}
AssetBundle
_initRootBundle
(
)
{
AssetBundle
_initRootBundle
(
)
{
...
...
packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart
View file @
8d2978af
...
@@ -109,6 +109,9 @@ class ScrollAwareImageProvider<T extends Object> extends ImageProvider<T> {
...
@@ -109,6 +109,9 @@ class ScrollAwareImageProvider<T extends Object> extends ImageProvider<T> {
@override
@override
ImageStreamCompleter
load
(
T
key
,
DecoderCallback
decode
)
=>
imageProvider
.
load
(
key
,
decode
);
ImageStreamCompleter
load
(
T
key
,
DecoderCallback
decode
)
=>
imageProvider
.
load
(
key
,
decode
);
@override
ImageStreamCompleter
loadBuffer
(
T
key
,
DecoderBufferCallback
decode
)
=>
imageProvider
.
loadBuffer
(
key
,
decode
);
@override
@override
Future
<
T
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
Future
<
T
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
}
}
packages/flutter/test/painting/image_cache_test.dart
View file @
8d2978af
...
@@ -2,7 +2,6 @@
...
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
...
@@ -136,15 +135,15 @@ void main() {
...
@@ -136,15 +135,15 @@ void main() {
});
});
test
(
'Returns null if an error is caught resolving an image'
,
()
{
test
(
'Returns null if an error is caught resolving an image'
,
()
{
Future
<
ui
.
Codec
>
basicDecoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
Future
<
ui
.
Codec
>
basicDecoder
(
ui
.
ImmutableBuffer
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
}
}
final
ErrorImageProvider
errorImage
=
ErrorImageProvider
();
final
ErrorImageProvider
errorImage
=
ErrorImageProvider
();
expect
(()
=>
imageCache
.
putIfAbsent
(
errorImage
,
()
=>
errorImage
.
load
(
errorImage
,
basicDecoder
)),
throwsA
(
isA
<
Error
>()));
expect
(()
=>
imageCache
.
putIfAbsent
(
errorImage
,
()
=>
errorImage
.
load
Buffer
(
errorImage
,
basicDecoder
)),
throwsA
(
isA
<
Error
>()));
bool
caughtError
=
false
;
bool
caughtError
=
false
;
final
ImageStreamCompleter
?
result
=
imageCache
.
putIfAbsent
(
final
ImageStreamCompleter
?
result
=
imageCache
.
putIfAbsent
(
errorImage
,
errorImage
,
()
=>
errorImage
.
load
(
errorImage
,
basicDecoder
),
()
=>
errorImage
.
load
Buffer
(
errorImage
,
basicDecoder
),
onError:
(
dynamic
error
,
StackTrace
?
stackTrace
)
{
onError:
(
dynamic
error
,
StackTrace
?
stackTrace
)
{
caughtError
=
true
;
caughtError
=
true
;
},
},
...
...
packages/flutter/test/painting/image_provider_and_image_cache_test.dart
View file @
8d2978af
...
@@ -17,8 +17,8 @@ import 'mocks_for_image_cache.dart';
...
@@ -17,8 +17,8 @@ import 'mocks_for_image_cache.dart';
void
main
(
)
{
void
main
(
)
{
TestRenderingFlutterBinding
.
ensureInitialized
();
TestRenderingFlutterBinding
.
ensureInitialized
();
Future
<
ui
.
Codec
>
basicDecoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
Future
<
ui
.
Codec
>
basicDecoder
(
ui
.
ImmutableBuffer
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
}
}
FlutterExceptionHandler
?
oldError
;
FlutterExceptionHandler
?
oldError
;
...
@@ -76,7 +76,7 @@ void main() {
...
@@ -76,7 +76,7 @@ void main() {
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
MemoryImage
imageProvider
=
MemoryImage
(
bytes
);
final
MemoryImage
imageProvider
=
MemoryImage
(
bytes
);
final
ImageStreamCompleter
cacheStream
=
otherCache
.
putIfAbsent
(
final
ImageStreamCompleter
cacheStream
=
otherCache
.
putIfAbsent
(
imageProvider
,
()
=>
imageProvider
.
load
(
imageProvider
,
basicDecoder
),
imageProvider
,
()
=>
imageProvider
.
load
Buffer
(
imageProvider
,
basicDecoder
),
)!;
)!;
final
ImageStream
stream
=
imageProvider
.
resolve
(
ImageConfiguration
.
empty
);
final
ImageStream
stream
=
imageProvider
.
resolve
(
ImageConfiguration
.
empty
);
final
Completer
<
void
>
completer
=
Completer
<
void
>();
final
Completer
<
void
>
completer
=
Completer
<
void
>();
...
...
packages/flutter/test/painting/image_provider_network_image_test.dart
View file @
8d2978af
...
@@ -6,7 +6,7 @@ import 'dart:async';
...
@@ -6,7 +6,7 @@ import 'dart:async';
import
'dart:io'
;
import
'dart:io'
;
import
'dart:math'
as
math
;
import
'dart:math'
as
math
;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
show
Codec
,
FrameInfo
;
import
'dart:ui'
show
Codec
,
FrameInfo
,
ImmutableBuffer
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/painting.dart'
;
import
'package:flutter/painting.dart'
;
...
@@ -18,8 +18,8 @@ import '../rendering/rendering_tester.dart';
...
@@ -18,8 +18,8 @@ import '../rendering/rendering_tester.dart';
void
main
(
)
{
void
main
(
)
{
TestRenderingFlutterBinding
.
ensureInitialized
();
TestRenderingFlutterBinding
.
ensureInitialized
();
Future
<
Codec
>
basicDecoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
Future
<
Codec
>
basicDecoder
(
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
buffer
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
}
}
late
_FakeHttpClient
httpClient
;
late
_FakeHttpClient
httpClient
;
...
@@ -77,7 +77,7 @@ void main() {
...
@@ -77,7 +77,7 @@ void main() {
Future
<
void
>
loadNetworkImage
()
async
{
Future
<
void
>
loadNetworkImage
()
async
{
final
NetworkImage
networkImage
=
NetworkImage
(
nonconst
(
'foo'
));
final
NetworkImage
networkImage
=
NetworkImage
(
nonconst
(
'foo'
));
final
ImageStreamCompleter
completer
=
networkImage
.
load
(
networkImage
,
basicDecoder
);
final
ImageStreamCompleter
completer
=
networkImage
.
load
Buffer
(
networkImage
,
basicDecoder
);
completer
.
addListener
(
ImageStreamListener
(
completer
.
addListener
(
ImageStreamListener
(
(
ImageInfo
image
,
bool
synchronousCall
)
{
},
(
ImageInfo
image
,
bool
synchronousCall
)
{
},
onError:
(
dynamic
error
,
StackTrace
?
stackTrace
)
{
onError:
(
dynamic
error
,
StackTrace
?
stackTrace
)
{
...
@@ -189,7 +189,7 @@ void main() {
...
@@ -189,7 +189,7 @@ void main() {
debugNetworkImageHttpClientProvider
=
null
;
debugNetworkImageHttpClientProvider
=
null
;
},
skip:
isBrowser
);
// [intended] Browser does not resolve images this way.
},
skip:
isBrowser
);
// [intended] Browser does not resolve images this way.
Future
<
Codec
>
decoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
async
{
Future
<
Codec
>
decoder
(
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
async
{
return
FakeCodec
();
return
FakeCodec
();
}
}
...
@@ -207,7 +207,7 @@ void main() {
...
@@ -207,7 +207,7 @@ void main() {
const
NetworkImage
provider
=
NetworkImage
(
url
);
const
NetworkImage
provider
=
NetworkImage
(
url
);
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
(
provider
,
decoder
)
as
MultiFrameImageStreamCompleter
;
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
Buffer
(
provider
,
decoder
)
as
MultiFrameImageStreamCompleter
;
expect
(
completer
.
debugLabel
,
url
);
expect
(
completer
.
debugLabel
,
url
);
});
});
...
...
packages/flutter/test/painting/image_provider_resize_image_test.dart
View file @
8d2978af
...
@@ -99,14 +99,14 @@ void main() {
...
@@ -99,14 +99,14 @@ void main() {
final
MemoryImage
memoryImage
=
MemoryImage
(
bytes
);
final
MemoryImage
memoryImage
=
MemoryImage
(
bytes
);
final
ResizeImage
resizeImage
=
ResizeImage
(
memoryImage
,
width:
123
,
height:
321
);
final
ResizeImage
resizeImage
=
ResizeImage
(
memoryImage
,
width:
123
,
height:
321
);
Future
<
ui
.
Codec
>
decode
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
})
{
Future
<
ui
.
Codec
>
decode
(
ui
.
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
})
{
expect
(
cacheWidth
,
123
);
expect
(
cacheWidth
,
123
);
expect
(
cacheHeight
,
321
);
expect
(
cacheHeight
,
321
);
expect
(
allowUpscaling
,
false
);
expect
(
allowUpscaling
,
false
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
buffer
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
);
}
}
resizeImage
.
load
(
await
resizeImage
.
obtainKey
(
ImageConfiguration
.
empty
),
decode
);
resizeImage
.
load
Buffer
(
await
resizeImage
.
obtainKey
(
ImageConfiguration
.
empty
),
decode
);
});
});
test
(
'ResizeImage handles sync obtainKey'
,
()
async
{
test
(
'ResizeImage handles sync obtainKey'
,
()
async
{
...
...
packages/flutter/test/painting/image_provider_test.dart
View file @
8d2978af
...
@@ -88,14 +88,14 @@ void main() {
...
@@ -88,14 +88,14 @@ void main() {
final
File
file
=
fs
.
file
(
'/empty.png'
)..
createSync
(
recursive:
true
);
final
File
file
=
fs
.
file
(
'/empty.png'
)..
createSync
(
recursive:
true
);
final
FileImage
provider
=
FileImage
(
file
);
final
FileImage
provider
=
FileImage
(
file
);
expect
(
provider
.
load
(
provider
,
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
async
{
expect
(
provider
.
load
Buffer
(
provider
,
(
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
async
{
return
Future
<
Codec
>.
value
(
FakeCodec
());
return
Future
<
Codec
>.
value
(
FakeCodec
());
}),
isA
<
MultiFrameImageStreamCompleter
>());
}),
isA
<
MultiFrameImageStreamCompleter
>());
expect
(
await
error
.
future
,
isStateError
);
expect
(
await
error
.
future
,
isStateError
);
});
});
Future
<
Codec
>
decoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
async
{
Future
<
Codec
>
decoder
(
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
async
{
return
FakeCodec
();
return
FakeCodec
();
}
}
...
@@ -104,7 +104,7 @@ void main() {
...
@@ -104,7 +104,7 @@ void main() {
final
File
file
=
fs
.
file
(
'/blue.png'
)..
createSync
(
recursive:
true
)..
writeAsBytesSync
(
kBlueSquarePng
);
final
File
file
=
fs
.
file
(
'/blue.png'
)..
createSync
(
recursive:
true
)..
writeAsBytesSync
(
kBlueSquarePng
);
final
FileImage
provider
=
FileImage
(
file
);
final
FileImage
provider
=
FileImage
(
file
);
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
(
provider
,
decoder
)
as
MultiFrameImageStreamCompleter
;
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
Buffer
(
provider
,
decoder
)
as
MultiFrameImageStreamCompleter
;
expect
(
completer
.
debugLabel
,
file
.
path
);
expect
(
completer
.
debugLabel
,
file
.
path
);
});
});
...
@@ -113,7 +113,7 @@ void main() {
...
@@ -113,7 +113,7 @@ void main() {
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kBlueSquarePng
);
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kBlueSquarePng
);
final
MemoryImage
provider
=
MemoryImage
(
bytes
);
final
MemoryImage
provider
=
MemoryImage
(
bytes
);
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
(
provider
,
decoder
)
as
MultiFrameImageStreamCompleter
;
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
Buffer
(
provider
,
decoder
)
as
MultiFrameImageStreamCompleter
;
expect
(
completer
.
debugLabel
,
'MemoryImage(
${describeIdentity(bytes)}
)'
);
expect
(
completer
.
debugLabel
,
'MemoryImage(
${describeIdentity(bytes)}
)'
);
});
});
...
@@ -122,7 +122,7 @@ void main() {
...
@@ -122,7 +122,7 @@ void main() {
const
String
asset
=
'images/blue.png'
;
const
String
asset
=
'images/blue.png'
;
final
ExactAssetImage
provider
=
ExactAssetImage
(
asset
,
bundle:
_TestAssetBundle
());
final
ExactAssetImage
provider
=
ExactAssetImage
(
asset
,
bundle:
_TestAssetBundle
());
final
AssetBundleImageKey
key
=
await
provider
.
obtainKey
(
ImageConfiguration
.
empty
);
final
AssetBundleImageKey
key
=
await
provider
.
obtainKey
(
ImageConfiguration
.
empty
);
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
(
key
,
decoder
)
as
MultiFrameImageStreamCompleter
;
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
Buffer
(
key
,
decoder
)
as
MultiFrameImageStreamCompleter
;
expect
(
completer
.
debugLabel
,
asset
);
expect
(
completer
.
debugLabel
,
asset
);
});
});
...
@@ -130,7 +130,7 @@ void main() {
...
@@ -130,7 +130,7 @@ void main() {
test
(
'Resize image sets tag'
,
()
async
{
test
(
'Resize image sets tag'
,
()
async
{
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kBlueSquarePng
);
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kBlueSquarePng
);
final
ResizeImage
provider
=
ResizeImage
(
MemoryImage
(
bytes
),
width:
40
,
height:
40
);
final
ResizeImage
provider
=
ResizeImage
(
MemoryImage
(
bytes
),
width:
40
,
height:
40
);
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
(
final
MultiFrameImageStreamCompleter
completer
=
provider
.
load
Buffer
(
await
provider
.
obtainKey
(
ImageConfiguration
.
empty
),
await
provider
.
obtainKey
(
ImageConfiguration
.
empty
),
decoder
,
decoder
,
)
as
MultiFrameImageStreamCompleter
;
)
as
MultiFrameImageStreamCompleter
;
...
...
packages/flutter/test/painting/image_resolution_test.dart
View file @
8d2978af
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/painting.dart'
;
import
'package:flutter/painting.dart'
;
...
@@ -34,6 +35,12 @@ class TestAssetBundle extends CachingAssetBundle {
...
@@ -34,6 +35,12 @@ class TestAssetBundle extends CachingAssetBundle {
}
}
throw
FlutterError
(
'key not found'
);
throw
FlutterError
(
'key not found'
);
}
}
@override
Future
<
ui
.
ImmutableBuffer
>
loadBuffer
(
String
key
)
async
{
final
ByteData
data
=
await
load
(
key
);
return
ui
.
ImmutableBuffer
.
fromUint8List
(
data
.
buffer
.
asUint8List
());
}
}
}
void
main
(
)
{
void
main
(
)
{
...
...
packages/flutter/test/painting/image_test_utils.dart
View file @
8d2978af
...
@@ -30,6 +30,11 @@ class TestImageProvider extends ImageProvider<TestImageProvider> {
...
@@ -30,6 +30,11 @@ class TestImageProvider extends ImageProvider<TestImageProvider> {
@override
@override
ImageStreamCompleter
load
(
TestImageProvider
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
TestImageProvider
key
,
DecoderCallback
decode
)
{
throw
UnsupportedError
(
'Use ImageProvider.loadBuffer instead.'
);
}
@override
ImageStreamCompleter
loadBuffer
(
TestImageProvider
key
,
DecoderBufferCallback
decode
)
{
loadCallCount
+=
1
;
loadCallCount
+=
1
;
return
OneFrameImageStreamCompleter
(
_completer
.
future
);
return
OneFrameImageStreamCompleter
(
_completer
.
future
);
}
}
...
...
packages/flutter/test/painting/mocks_for_image_cache.dart
View file @
8d2978af
...
@@ -86,6 +86,11 @@ Future<ImageInfo> extractOneFrame(ImageStream stream) {
...
@@ -86,6 +86,11 @@ Future<ImageInfo> extractOneFrame(ImageStream stream) {
}
}
class
ErrorImageProvider
extends
ImageProvider
<
ErrorImageProvider
>
{
class
ErrorImageProvider
extends
ImageProvider
<
ErrorImageProvider
>
{
@override
ImageStreamCompleter
loadBuffer
(
ErrorImageProvider
key
,
DecoderBufferCallback
decode
)
{
throw
Error
();
}
@override
@override
ImageStreamCompleter
load
(
ErrorImageProvider
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
ErrorImageProvider
key
,
DecoderCallback
decode
)
{
throw
Error
();
throw
Error
();
...
@@ -99,7 +104,7 @@ class ErrorImageProvider extends ImageProvider<ErrorImageProvider> {
...
@@ -99,7 +104,7 @@ class ErrorImageProvider extends ImageProvider<ErrorImageProvider> {
class
ObtainKeyErrorImageProvider
extends
ImageProvider
<
ObtainKeyErrorImageProvider
>
{
class
ObtainKeyErrorImageProvider
extends
ImageProvider
<
ObtainKeyErrorImageProvider
>
{
@override
@override
ImageStreamCompleter
load
(
ObtainKeyErrorImageProvider
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
ObtainKeyErrorImageProvider
key
,
DecoderBuff
erCallback
decode
)
{
throw
Error
();
throw
Error
();
}
}
...
@@ -107,11 +112,16 @@ class ObtainKeyErrorImageProvider extends ImageProvider<ObtainKeyErrorImageProvi
...
@@ -107,11 +112,16 @@ class ObtainKeyErrorImageProvider extends ImageProvider<ObtainKeyErrorImageProvi
Future
<
ObtainKeyErrorImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
Future
<
ObtainKeyErrorImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
throw
Error
();
throw
Error
();
}
}
@override
ImageStreamCompleter
load
(
ObtainKeyErrorImageProvider
key
,
DecoderCallback
decode
)
{
throw
UnimplementedError
();
}
}
}
class
LoadErrorImageProvider
extends
ImageProvider
<
LoadErrorImageProvider
>
{
class
LoadErrorImageProvider
extends
ImageProvider
<
LoadErrorImageProvider
>
{
@override
@override
ImageStreamCompleter
load
(
LoadErrorImageProvider
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
LoadErrorImageProvider
key
,
DecoderBuff
erCallback
decode
)
{
throw
Error
();
throw
Error
();
}
}
...
@@ -119,6 +129,11 @@ class LoadErrorImageProvider extends ImageProvider<LoadErrorImageProvider> {
...
@@ -119,6 +129,11 @@ class LoadErrorImageProvider extends ImageProvider<LoadErrorImageProvider> {
Future
<
LoadErrorImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
Future
<
LoadErrorImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
return
SynchronousFuture
<
LoadErrorImageProvider
>(
this
);
return
SynchronousFuture
<
LoadErrorImageProvider
>(
this
);
}
}
@override
ImageStreamCompleter
load
(
LoadErrorImageProvider
key
,
DecoderCallback
decode
)
{
throw
UnimplementedError
();
}
}
}
class
LoadErrorCompleterImageProvider
extends
ImageProvider
<
LoadErrorCompleterImageProvider
>
{
class
LoadErrorCompleterImageProvider
extends
ImageProvider
<
LoadErrorCompleterImageProvider
>
{
...
...
packages/flutter/test/widgets/fade_in_image_test.dart
View file @
8d2978af
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
as
ui
;
...
@@ -58,8 +59,8 @@ class LoadTestImageProvider extends ImageProvider<Object> {
...
@@ -58,8 +59,8 @@ class LoadTestImageProvider extends ImageProvider<Object> {
final
ImageProvider
provider
;
final
ImageProvider
provider
;
ImageStreamCompleter
testLoad
(
Object
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
testLoad
(
Object
key
,
Decoder
Buffer
Callback
decode
)
{
return
provider
.
load
(
key
,
decode
);
return
provider
.
load
Buffer
(
key
,
decode
);
}
}
@override
@override
...
@@ -339,7 +340,7 @@ Future<void> main() async {
...
@@ -339,7 +340,7 @@ Future<void> main() async {
group
(
'ImageProvider'
,
()
{
group
(
'ImageProvider'
,
()
{
test
Widgets
(
'memory placeholder cacheWidth and cacheHeight is passed through'
,
(
WidgetTester
tester
)
async
{
test
(
'memory placeholder cacheWidth and cacheHeight is passed through'
,
(
)
async
{
final
Uint8List
testBytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
Uint8List
testBytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
FadeInImage
image
=
FadeInImage
.
memoryNetwork
(
final
FadeInImage
image
=
FadeInImage
.
memoryNetwork
(
placeholder:
testBytes
,
placeholder:
testBytes
,
...
@@ -351,22 +352,29 @@ Future<void> main() async {
...
@@ -351,22 +352,29 @@ Future<void> main() async {
);
);
bool
called
=
false
;
bool
called
=
false
;
Future
<
ui
.
Codec
>
decode
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
})
{
Future
<
ui
.
Codec
>
decode
(
ui
.
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
})
{
expect
(
cacheWidth
,
20
);
expect
(
cacheWidth
,
20
);
expect
(
cacheHeight
,
30
);
expect
(
cacheHeight
,
30
);
expect
(
allowUpscaling
,
false
);
expect
(
allowUpscaling
,
false
);
called
=
true
;
called
=
true
;
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
buffer
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
);
}
}
final
ImageProvider
resizeImage
=
image
.
placeholder
;
final
ImageProvider
resizeImage
=
image
.
placeholder
;
expect
(
image
.
placeholder
,
isA
<
ResizeImage
>());
expect
(
image
.
placeholder
,
isA
<
ResizeImage
>());
expect
(
called
,
false
);
expect
(
called
,
false
);
final
LoadTestImageProvider
testProvider
=
LoadTestImageProvider
(
image
.
placeholder
);
final
LoadTestImageProvider
testProvider
=
LoadTestImageProvider
(
image
.
placeholder
);
testProvider
.
testLoad
(
await
resizeImage
.
obtainKey
(
ImageConfiguration
.
empty
),
decode
);
final
ImageStreamCompleter
streamCompleter
=
testProvider
.
testLoad
(
await
resizeImage
.
obtainKey
(
ImageConfiguration
.
empty
),
decode
);
final
Completer
<
void
>
completer
=
Completer
<
void
>();
streamCompleter
.
addListener
(
ImageStreamListener
((
ImageInfo
imageInfo
,
bool
syncCall
)
{
completer
.
complete
();
}));
await
completer
.
future
;
expect
(
called
,
true
);
expect
(
called
,
true
);
});
});
test
Widgets
(
'do not resize when null cache dimensions'
,
(
WidgetTester
tester
)
async
{
test
(
'do not resize when null cache dimensions'
,
(
)
async
{
final
Uint8List
testBytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
Uint8List
testBytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
FadeInImage
image
=
FadeInImage
.
memoryNetwork
(
final
FadeInImage
image
=
FadeInImage
.
memoryNetwork
(
placeholder:
testBytes
,
placeholder:
testBytes
,
...
@@ -374,19 +382,26 @@ Future<void> main() async {
...
@@ -374,19 +382,26 @@ Future<void> main() async {
);
);
bool
called
=
false
;
bool
called
=
false
;
Future
<
ui
.
Codec
>
decode
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
})
{
Future
<
ui
.
Codec
>
decode
(
ui
.
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
allowUpscaling
=
false
})
{
expect
(
cacheWidth
,
null
);
expect
(
cacheWidth
,
null
);
expect
(
cacheHeight
,
null
);
expect
(
cacheHeight
,
null
);
expect
(
allowUpscaling
,
false
);
expect
(
allowUpscaling
,
false
);
called
=
true
;
called
=
true
;
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
);
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
buffer
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
);
}
}
// image.placeholder should be an instance of MemoryImage instead of ResizeImage
// image.placeholder should be an instance of MemoryImage instead of ResizeImage
final
ImageProvider
memoryImage
=
image
.
placeholder
;
final
ImageProvider
memoryImage
=
image
.
placeholder
;
expect
(
image
.
placeholder
,
isA
<
MemoryImage
>());
expect
(
image
.
placeholder
,
isA
<
MemoryImage
>());
expect
(
called
,
false
);
expect
(
called
,
false
);
final
LoadTestImageProvider
testProvider
=
LoadTestImageProvider
(
image
.
placeholder
);
final
LoadTestImageProvider
testProvider
=
LoadTestImageProvider
(
image
.
placeholder
);
testProvider
.
testLoad
(
await
memoryImage
.
obtainKey
(
ImageConfiguration
.
empty
),
decode
);
final
ImageStreamCompleter
streamCompleter
=
testProvider
.
testLoad
(
await
memoryImage
.
obtainKey
(
ImageConfiguration
.
empty
),
decode
);
final
Completer
<
void
>
completer
=
Completer
<
void
>();
streamCompleter
.
addListener
(
ImageStreamListener
((
ImageInfo
imageInfo
,
bool
syncCall
)
{
completer
.
complete
();
}));
await
completer
.
future
;
expect
(
called
,
true
);
expect
(
called
,
true
);
});
});
});
});
...
...
packages/flutter/test/widgets/image_resolution_test.dart
View file @
8d2978af
...
@@ -84,7 +84,7 @@ class TestAssetImage extends AssetImage {
...
@@ -84,7 +84,7 @@ class TestAssetImage extends AssetImage {
final
Map
<
double
,
ui
.
Image
>
images
;
final
Map
<
double
,
ui
.
Image
>
images
;
@override
@override
ImageStreamCompleter
load
(
AssetBundleImageKey
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
AssetBundleImageKey
key
,
DecoderBuff
erCallback
decode
)
{
late
ImageInfo
imageInfo
;
late
ImageInfo
imageInfo
;
key
.
bundle
.
load
(
key
.
name
).
then
<
void
>((
ByteData
data
)
{
key
.
bundle
.
load
(
key
.
name
).
then
<
void
>((
ByteData
data
)
{
final
ui
.
Image
image
=
images
[
scaleOf
(
data
)]!;
final
ui
.
Image
image
=
images
[
scaleOf
(
data
)]!;
...
...
packages/flutter/test/widgets/image_test.dart
View file @
8d2978af
...
@@ -2122,7 +2122,7 @@ class _DebouncingImageProvider extends ImageProvider<Object> {
...
@@ -2122,7 +2122,7 @@ class _DebouncingImageProvider extends ImageProvider<Object> {
Future
<
Object
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
Future
<
Object
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
@override
@override
ImageStreamCompleter
load
(
Object
key
,
DecoderCallback
decode
)
=>
imageProvider
.
load
(
key
,
decode
);
ImageStreamCompleter
load
Buffer
(
Object
key
,
DecoderBufferCallback
decode
)
=>
imageProvider
.
loadBuffer
(
key
,
decode
);
}
}
class
_FailingImageProvider
extends
ImageProvider
<
int
>
{
class
_FailingImageProvider
extends
ImageProvider
<
int
>
{
...
...
packages/flutter/test/widgets/scroll_aware_image_provider_test.dart
View file @
8d2978af
...
@@ -322,7 +322,7 @@ void main() {
...
@@ -322,7 +322,7 @@ void main() {
// If we miss the early return, we will fail.
// If we miss the early return, we will fail.
testImageProvider
.
complete
();
testImageProvider
.
complete
();
imageCache
.
putIfAbsent
(
testImageProvider
,
()
=>
testImageProvider
.
load
(
testImageProvider
,
PaintingBinding
.
instance
.
instantiateImageCodec
));
imageCache
.
putIfAbsent
(
testImageProvider
,
()
=>
testImageProvider
.
load
Buffer
(
testImageProvider
,
PaintingBinding
.
instance
.
instantiateImageCodecFromBuffer
));
// We've stopped scrolling fast.
// We've stopped scrolling fast.
physics
.
recommendDeferredLoadingValue
=
false
;
physics
.
recommendDeferredLoadingValue
=
false
;
await
tester
.
idle
();
await
tester
.
idle
();
...
@@ -377,7 +377,7 @@ void main() {
...
@@ -377,7 +377,7 @@ void main() {
// Complete the original image while we're still scrolling fast.
// Complete the original image while we're still scrolling fast.
testImageProvider
.
complete
();
testImageProvider
.
complete
();
stream
.
setCompleter
(
testImageProvider
.
load
(
testImageProvider
,
PaintingBinding
.
instance
.
instantiateImageCodec
));
stream
.
setCompleter
(
testImageProvider
.
load
Buffer
(
testImageProvider
,
PaintingBinding
.
instance
.
instantiateImageCodecFromBuffer
));
// Verify that this hasn't changed the cache state yet
// Verify that this hasn't changed the cache state yet
expect
(
imageCache
.
containsKey
(
testImageProvider
),
false
);
expect
(
imageCache
.
containsKey
(
testImageProvider
),
false
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment