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
Expand all
Hide 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 @@
import
'dart:convert'
;
import
'dart:ui'
as
ui
show
Codec
;
import
'dart:ui'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
...
...
@@ -57,11 +58,11 @@ class DelayedBase64Image extends ImageProvider<int> {
}
@override
ImageStreamCompleter
load
(
int
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
int
key
,
DecoderBuff
erCallback
decode
)
{
return
MultiFrameImageStreamCompleter
(
codec:
Future
<
ui
.
Codec
>.
delayed
(
delay
,
()
=>
decode
(
base64
.
decode
(
data
)),
()
async
=>
decode
(
await
ImmutableBuffer
.
fromUint8List
(
base64
.
decode
(
data
)
)),
),
scale:
1.0
,
);
...
...
dev/benchmarks/microbenchmarks/lib/ui/image_bench.dart
View file @
8d2978af
...
...
@@ -87,9 +87,7 @@ Future<void> main() async {
for
(
int
i
=
0
;
i
<
10
;
i
+=
1
)
{
await
Future
.
wait
(<
Future
<
ui
.
ImmutableBuffer
>>[
for
(
String
asset
in
assets
)
rootBundle
.
load
(
asset
).
then
((
ByteData
data
)
{
return
ui
.
ImmutableBuffer
.
fromUint8List
(
data
.
buffer
.
asUint8List
());
})
rootBundle
.
loadBuffer
(
asset
)
]);
}
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
final
StreamController
<
ImageChunkEvent
>
chunkEvents
=
StreamController
<
ImageChunkEvent
>();
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
,
scale:
key
.
scale
,
debugLabel:
key
.
url
,
...
...
@@ -77,7 +96,8 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
Future
<
ui
.
Codec
>
_loadAsync
(
NetworkImage
key
,
StreamController
<
ImageChunkEvent
>
chunkEvents
,
image_provider
.
DecoderCallback
decode
,
image_provider
.
DecoderBufferCallback
?
decode
,
image_provider
.
DecoderCallback
?
decodeDepreacted
,
)
async
{
try
{
assert
(
key
==
this
);
...
...
@@ -111,7 +131,13 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
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
)
{
// 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.
...
...
packages/flutter/lib/src/painting/_network_image_web.dart
View file @
8d2978af
...
...
@@ -66,7 +66,24 @@ class NetworkImage
return
MultiFrameImageStreamCompleter
(
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
,
debugLabel:
key
.
url
,
informationCollector:
_imageStreamInformationCollector
(
key
),
...
...
@@ -93,7 +110,8 @@ class NetworkImage
// directly in place of the typical `instantiateImageCodec` method.
Future
<
ui
.
Codec
>
_loadAsync
(
NetworkImage
key
,
image_provider
.
DecoderCallback
decode
,
image_provider
.
DecoderBufferCallback
?
decode
,
image_provider
.
DecoderCallback
?
decodeDepreacted
,
StreamController
<
ImageChunkEvent
>
chunkEvents
,
)
async
{
assert
(
key
==
this
);
...
...
@@ -144,7 +162,13 @@ class NetworkImage
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
{
// This API only exists in the web engine implementation and is not
// contained in the analyzer summary for Flutter.
...
...
packages/flutter/lib/src/painting/binding.dart
View file @
8d2978af
...
...
@@ -3,7 +3,7 @@
// found in the LICENSE file.
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/services.dart'
show
ServicesBinding
;
...
...
@@ -81,6 +81,9 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// 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.
///
...
...
@@ -97,6 +100,10 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// unnecessary memory usage for images. Callers that wish to display an image
/// above its native resolution should prefer scaling the canvas the image is
/// drawn into.
@Deprecated
(
'Use instantiateImageCodecFromBuffer with an ImmutableBuffer instance instead. '
'This feature was deprecated after v2.13.0-1.0.pre.'
,
)
Future
<
ui
.
Codec
>
instantiateImageCodec
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
...
...
@@ -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
void
evict
(
String
asset
)
{
super
.
evict
(
asset
);
...
...
packages/flutter/lib/src/painting/image_provider.dart
View file @
8d2978af
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/services/asset_bundle.dart
View file @
8d2978af
...
...
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
...
...
@@ -55,6 +55,15 @@ abstract class AssetBundle {
/// Throws an exception if the asset is not found.
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.
///
/// Throws an exception if the asset is not found.
...
...
@@ -228,6 +237,12 @@ abstract class CachingAssetBundle extends AssetBundle {
_stringCache
.
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.
...
...
@@ -242,6 +257,19 @@ class PlatformAssetBundle extends CachingAssetBundle {
}
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
(
)
{
...
...
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> {
@override
ImageStreamCompleter
load
(
T
key
,
DecoderCallback
decode
)
=>
imageProvider
.
load
(
key
,
decode
);
@override
ImageStreamCompleter
loadBuffer
(
T
key
,
DecoderBufferCallback
decode
)
=>
imageProvider
.
loadBuffer
(
key
,
decode
);
@override
Future
<
T
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
}
packages/flutter/test/painting/image_cache_test.dart
View file @
8d2978af
...
...
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
...
...
@@ -136,15 +135,15 @@ void main() {
});
test
(
'Returns null if an error is caught resolving an image'
,
()
{
Future
<
ui
.
Codec
>
basicDecoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
Future
<
ui
.
Codec
>
basicDecoder
(
ui
.
ImmutableBuffer
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
}
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
;
final
ImageStreamCompleter
?
result
=
imageCache
.
putIfAbsent
(
errorImage
,
()
=>
errorImage
.
load
(
errorImage
,
basicDecoder
),
()
=>
errorImage
.
load
Buffer
(
errorImage
,
basicDecoder
),
onError:
(
dynamic
error
,
StackTrace
?
stackTrace
)
{
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';
void
main
(
)
{
TestRenderingFlutterBinding
.
ensureInitialized
();
Future
<
ui
.
Codec
>
basicDecoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
Future
<
ui
.
Codec
>
basicDecoder
(
ui
.
ImmutableBuffer
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
}
FlutterExceptionHandler
?
oldError
;
...
...
@@ -76,7 +76,7 @@ void main() {
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kTransparentImage
);
final
MemoryImage
imageProvider
=
MemoryImage
(
bytes
);
final
ImageStreamCompleter
cacheStream
=
otherCache
.
putIfAbsent
(
imageProvider
,
()
=>
imageProvider
.
load
(
imageProvider
,
basicDecoder
),
imageProvider
,
()
=>
imageProvider
.
load
Buffer
(
imageProvider
,
basicDecoder
),
)!;
final
ImageStream
stream
=
imageProvider
.
resolve
(
ImageConfiguration
.
empty
);
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';
import
'dart:io'
;
import
'dart:math'
as
math
;
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/painting.dart'
;
...
...
@@ -18,8 +18,8 @@ import '../rendering/rendering_tester.dart';
void
main
(
)
{
TestRenderingFlutterBinding
.
ensureInitialized
();
Future
<
Codec
>
basicDecoder
(
Uint8List
bytes
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
(
bytes
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
Future
<
Codec
>
basicDecoder
(
ImmutableBuffer
buffer
,
{
int
?
cacheWidth
,
int
?
cacheHeight
,
bool
?
allowUpscaling
})
{
return
PaintingBinding
.
instance
.
instantiateImageCodec
FromBuffer
(
buffer
,
cacheWidth:
cacheWidth
,
cacheHeight:
cacheHeight
,
allowUpscaling:
allowUpscaling
??
false
);
}
late
_FakeHttpClient
httpClient
;
...
...
@@ -77,7 +77,7 @@ void main() {
Future
<
void
>
loadNetworkImage
()
async
{
final
NetworkImage
networkImage
=
NetworkImage
(
nonconst
(
'foo'
));
final
ImageStreamCompleter
completer
=
networkImage
.
load
(
networkImage
,
basicDecoder
);
final
ImageStreamCompleter
completer
=
networkImage
.
load
Buffer
(
networkImage
,
basicDecoder
);
completer
.
addListener
(
ImageStreamListener
(
(
ImageInfo
image
,
bool
synchronousCall
)
{
},
onError:
(
dynamic
error
,
StackTrace
?
stackTrace
)
{
...
...
@@ -189,7 +189,7 @@ void main() {
debugNetworkImageHttpClientProvider
=
null
;
},
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
();
}
...
...
@@ -207,7 +207,7 @@ void main() {
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
);
});
...
...
packages/flutter/test/painting/image_provider_resize_image_test.dart
View file @
8d2978af
...
...
@@ -99,14 +99,14 @@ void main() {
final
MemoryImage
memoryImage
=
MemoryImage
(
bytes
);
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
(
cacheHeight
,
321
);
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
{
...
...
packages/flutter/test/painting/image_provider_test.dart
View file @
8d2978af
...
...
@@ -88,14 +88,14 @@ void main() {
final
File
file
=
fs
.
file
(
'/empty.png'
)..
createSync
(
recursive:
true
);
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
());
}),
isA
<
MultiFrameImageStreamCompleter
>());
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
();
}
...
...
@@ -104,7 +104,7 @@ void main() {
final
File
file
=
fs
.
file
(
'/blue.png'
)..
createSync
(
recursive:
true
)..
writeAsBytesSync
(
kBlueSquarePng
);
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
);
});
...
...
@@ -113,7 +113,7 @@ void main() {
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kBlueSquarePng
);
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)}
)'
);
});
...
...
@@ -122,7 +122,7 @@ void main() {
const
String
asset
=
'images/blue.png'
;
final
ExactAssetImage
provider
=
ExactAssetImage
(
asset
,
bundle:
_TestAssetBundle
());
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
);
});
...
...
@@ -130,7 +130,7 @@ void main() {
test
(
'Resize image sets tag'
,
()
async
{
final
Uint8List
bytes
=
Uint8List
.
fromList
(
kBlueSquarePng
);
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
),
decoder
,
)
as
MultiFrameImageStreamCompleter
;
...
...
packages/flutter/test/painting/image_resolution_test.dart
View file @
8d2978af
...
...
@@ -4,6 +4,7 @@
import
'dart:convert'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/painting.dart'
;
...
...
@@ -34,6 +35,12 @@ class TestAssetBundle extends CachingAssetBundle {
}
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
(
)
{
...
...
packages/flutter/test/painting/image_test_utils.dart
View file @
8d2978af
...
...
@@ -30,6 +30,11 @@ class TestImageProvider extends ImageProvider<TestImageProvider> {
@override
ImageStreamCompleter
load
(
TestImageProvider
key
,
DecoderCallback
decode
)
{
throw
UnsupportedError
(
'Use ImageProvider.loadBuffer instead.'
);
}
@override
ImageStreamCompleter
loadBuffer
(
TestImageProvider
key
,
DecoderBufferCallback
decode
)
{
loadCallCount
+=
1
;
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) {
}
class
ErrorImageProvider
extends
ImageProvider
<
ErrorImageProvider
>
{
@override
ImageStreamCompleter
loadBuffer
(
ErrorImageProvider
key
,
DecoderBufferCallback
decode
)
{
throw
Error
();
}
@override
ImageStreamCompleter
load
(
ErrorImageProvider
key
,
DecoderCallback
decode
)
{
throw
Error
();
...
...
@@ -99,7 +104,7 @@ class ErrorImageProvider extends ImageProvider<ErrorImageProvider> {
class
ObtainKeyErrorImageProvider
extends
ImageProvider
<
ObtainKeyErrorImageProvider
>
{
@override
ImageStreamCompleter
load
(
ObtainKeyErrorImageProvider
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
ObtainKeyErrorImageProvider
key
,
DecoderBuff
erCallback
decode
)
{
throw
Error
();
}
...
...
@@ -107,11 +112,16 @@ class ObtainKeyErrorImageProvider extends ImageProvider<ObtainKeyErrorImageProvi
Future
<
ObtainKeyErrorImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
throw
Error
();
}
@override
ImageStreamCompleter
load
(
ObtainKeyErrorImageProvider
key
,
DecoderCallback
decode
)
{
throw
UnimplementedError
();
}
}
class
LoadErrorImageProvider
extends
ImageProvider
<
LoadErrorImageProvider
>
{
@override
ImageStreamCompleter
load
(
LoadErrorImageProvider
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
LoadErrorImageProvider
key
,
DecoderBuff
erCallback
decode
)
{
throw
Error
();
}
...
...
@@ -119,6 +129,11 @@ class LoadErrorImageProvider extends ImageProvider<LoadErrorImageProvider> {
Future
<
LoadErrorImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
return
SynchronousFuture
<
LoadErrorImageProvider
>(
this
);
}
@override
ImageStreamCompleter
load
(
LoadErrorImageProvider
key
,
DecoderCallback
decode
)
{
throw
UnimplementedError
();
}
}
class
LoadErrorCompleterImageProvider
extends
ImageProvider
<
LoadErrorCompleterImageProvider
>
{
...
...
packages/flutter/test/widgets/fade_in_image_test.dart
View file @
8d2978af
...
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
...
...
@@ -58,8 +59,8 @@ class LoadTestImageProvider extends ImageProvider<Object> {
final
ImageProvider
provider
;
ImageStreamCompleter
testLoad
(
Object
key
,
DecoderCallback
decode
)
{
return
provider
.
load
(
key
,
decode
);
ImageStreamCompleter
testLoad
(
Object
key
,
Decoder
Buffer
Callback
decode
)
{
return
provider
.
load
Buffer
(
key
,
decode
);
}
@override
...
...
@@ -339,7 +340,7 @@ Future<void> main() async {
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
FadeInImage
image
=
FadeInImage
.
memoryNetwork
(
placeholder:
testBytes
,
...
...
@@ -351,22 +352,29 @@ Future<void> main() async {
);
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
(
cacheHeight
,
30
);
expect
(
allowUpscaling
,
false
);
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
;
expect
(
image
.
placeholder
,
isA
<
ResizeImage
>());
expect
(
called
,
false
);
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
);
});
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
FadeInImage
image
=
FadeInImage
.
memoryNetwork
(
placeholder:
testBytes
,
...
...
@@ -374,19 +382,26 @@ Future<void> main() async {
);
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
(
cacheHeight
,
null
);
expect
(
allowUpscaling
,
false
);
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
final
ImageProvider
memoryImage
=
image
.
placeholder
;
expect
(
image
.
placeholder
,
isA
<
MemoryImage
>());
expect
(
called
,
false
);
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
);
});
});
...
...
packages/flutter/test/widgets/image_resolution_test.dart
View file @
8d2978af
...
...
@@ -84,7 +84,7 @@ class TestAssetImage extends AssetImage {
final
Map
<
double
,
ui
.
Image
>
images
;
@override
ImageStreamCompleter
load
(
AssetBundleImageKey
key
,
Decod
erCallback
decode
)
{
ImageStreamCompleter
load
Buffer
(
AssetBundleImageKey
key
,
DecoderBuff
erCallback
decode
)
{
late
ImageInfo
imageInfo
;
key
.
bundle
.
load
(
key
.
name
).
then
<
void
>((
ByteData
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> {
Future
<
Object
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
@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
>
{
...
...
packages/flutter/test/widgets/scroll_aware_image_provider_test.dart
View file @
8d2978af
...
...
@@ -322,7 +322,7 @@ void main() {
// If we miss the early return, we will fail.
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.
physics
.
recommendDeferredLoadingValue
=
false
;
await
tester
.
idle
();
...
...
@@ -377,7 +377,7 @@ void main() {
// Complete the original image while we're still scrolling fast.
testImageProvider
.
complete
();
stream
.
setCompleter
(
testImageProvider
.
load
(
testImageProvider
,
PaintingBinding
.
instance
.
instantiateImageCodec
));
stream
.
setCompleter
(
testImageProvider
.
load
Buffer
(
testImageProvider
,
PaintingBinding
.
instance
.
instantiateImageCodecFromBuffer
));
// Verify that this hasn't changed the cache state yet
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