Unverified Commit af178605 authored by Gary Qian's avatar Gary Qian Committed by GitHub

Detect sync vs async obtainKey in ResizeImage (#51081)

parent dda7a618
...@@ -726,9 +726,28 @@ class ResizeImage extends ImageProvider<_SizeAwareCacheKey> { ...@@ -726,9 +726,28 @@ class ResizeImage extends ImageProvider<_SizeAwareCacheKey> {
} }
@override @override
Future<_SizeAwareCacheKey> obtainKey(ImageConfiguration configuration) async { Future<_SizeAwareCacheKey> obtainKey(ImageConfiguration configuration) {
final Object providerCacheKey = await imageProvider.obtainKey(configuration); Completer<_SizeAwareCacheKey> completer;
return _SizeAwareCacheKey(providerCacheKey, width, height); // 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() { ...@@ -395,6 +395,32 @@ void main() {
resizeImage.load(await resizeImage.obtainKey(ImageConfiguration.empty), decode); 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 { test('File image with empty file throws expected error (load)', () async {
final Completer<StateError> error = Completer<StateError>(); final Completer<StateError> error = Completer<StateError>();
FlutterError.onError = (FlutterErrorDetails details) { FlutterError.onError = (FlutterErrorDetails details) {
...@@ -425,6 +451,17 @@ Future<Size> _resolveAndGetSize(ImageProvider imageProvider, ...@@ -425,6 +451,17 @@ Future<Size> _resolveAndGetSize(ImageProvider imageProvider,
return await completer.future; 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 MockHttpClient extends Mock implements HttpClient {}
class MockHttpClientRequest extends Mock implements HttpClientRequest {} class MockHttpClientRequest extends Mock implements HttpClientRequest {}
class MockHttpClientResponse extends Mock implements HttpClientResponse {} class MockHttpClientResponse extends Mock implements HttpClientResponse {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment