mirror of
https://github.com/flutter/flutter
synced 2024-10-14 04:02:56 +00:00
Detect sync vs async obtainKey in ResizeImage (#51081)
This commit is contained in:
parent
dda7a618ec
commit
af17860513
|
@ -726,9 +726,28 @@ class ResizeImage extends ImageProvider<_SizeAwareCacheKey> {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<_SizeAwareCacheKey> obtainKey(ImageConfiguration configuration) async {
|
||||
final Object providerCacheKey = await imageProvider.obtainKey(configuration);
|
||||
return _SizeAwareCacheKey(providerCacheKey, width, height);
|
||||
Future<_SizeAwareCacheKey> obtainKey(ImageConfiguration configuration) {
|
||||
Completer<_SizeAwareCacheKey> completer;
|
||||
// If the imageProvider.obtainKey future is synchronous, then we will be able to fill in result with
|
||||
// a value before completer is initialized below.
|
||||
SynchronousFuture<_SizeAwareCacheKey> result;
|
||||
imageProvider.obtainKey(configuration).then((Object key) {
|
||||
if (completer == null) {
|
||||
// This future has completed synchronously (completer was never assigned),
|
||||
// so we can directly create the synchronous result to return.
|
||||
result = SynchronousFuture<_SizeAwareCacheKey>(_SizeAwareCacheKey(key, width, height));
|
||||
} else {
|
||||
// This future did not synchronously complete.
|
||||
completer.complete(_SizeAwareCacheKey(key, width, height));
|
||||
}
|
||||
});
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
// If the code reaches here, it means the the imageProvider.obtainKey was not
|
||||
// completed sync, so we initialize the completer for completion later.
|
||||
completer = Completer<_SizeAwareCacheKey>();
|
||||
return completer.future;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -395,6 +395,32 @@ void main() {
|
|||
resizeImage.load(await resizeImage.obtainKey(ImageConfiguration.empty), decode);
|
||||
});
|
||||
|
||||
test('ResizeImage handles sync obtainKey', () async {
|
||||
final Uint8List bytes = Uint8List.fromList(kTransparentImage);
|
||||
final MemoryImage memoryImage = MemoryImage(bytes);
|
||||
final ResizeImage resizeImage = ResizeImage(memoryImage, width: 123, height: 321);
|
||||
|
||||
bool isAsync = false;
|
||||
resizeImage.obtainKey(ImageConfiguration.empty).then((Object key) {
|
||||
expect(isAsync, false);
|
||||
});
|
||||
isAsync = true;
|
||||
expect(isAsync, true);
|
||||
});
|
||||
|
||||
test('ResizeImage handles async obtainKey', () async {
|
||||
final Uint8List bytes = Uint8List.fromList(kTransparentImage);
|
||||
final AsyncKeyMemoryImage memoryImage = AsyncKeyMemoryImage(bytes);
|
||||
final ResizeImage resizeImage = ResizeImage(memoryImage, width: 123, height: 321);
|
||||
|
||||
bool isAsync = false;
|
||||
resizeImage.obtainKey(ImageConfiguration.empty).then((Object key) {
|
||||
expect(isAsync, true);
|
||||
});
|
||||
isAsync = true;
|
||||
expect(isAsync, true);
|
||||
});
|
||||
|
||||
test('File image with empty file throws expected error (load)', () async {
|
||||
final Completer<StateError> error = Completer<StateError>();
|
||||
FlutterError.onError = (FlutterErrorDetails details) {
|
||||
|
@ -425,6 +451,17 @@ Future<Size> _resolveAndGetSize(ImageProvider imageProvider,
|
|||
return await completer.future;
|
||||
}
|
||||
|
||||
// This version of MemoryImage guarantees obtainKey returns a future that has not been
|
||||
// completed synchronously.
|
||||
class AsyncKeyMemoryImage extends MemoryImage {
|
||||
AsyncKeyMemoryImage(Uint8List bytes) : super(bytes);
|
||||
|
||||
@override
|
||||
Future<MemoryImage> obtainKey(ImageConfiguration configuration) {
|
||||
return Future<MemoryImage>(() => this);
|
||||
}
|
||||
}
|
||||
|
||||
class MockHttpClient extends Mock implements HttpClient {}
|
||||
class MockHttpClientRequest extends Mock implements HttpClientRequest {}
|
||||
class MockHttpClientResponse extends Mock implements HttpClientResponse {}
|
||||
|
|
Loading…
Reference in a new issue