Unverified Commit 30738982 authored by Dan Field's avatar Dan Field Committed by GitHub

Remove network images from cache on any exception during loading (#53875)

* Remove network images from cache on any exception during loading
parent 4e811d28
......@@ -82,7 +82,9 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
assert(key == this);
final Uri resolved = Uri.base.resolve(key.url);
final HttpClientRequest request = await _httpClient.getUrl(resolved);
headers?.forEach((String name, String value) {
request.headers.add(name, value);
});
......@@ -91,7 +93,6 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
// The network may be only temporarily unavailable, or the file will be
// added on the server later. Avoid having future calls to resolve
// fail to check the network again.
PaintingBinding.instance.imageCache.evict(key);
throw image_provider.NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
}
......@@ -108,6 +109,14 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
throw Exception('NetworkImage is an empty file: $resolved');
return decode(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.
// Schedule a microtask to give the cache a chance to add the key.
scheduleMicrotask(() {
PaintingBinding.instance.imageCache.evict(key);
});
rethrow;
} finally {
chunkEvents.close();
}
......
......@@ -396,6 +396,39 @@ void main() {
expect(events[i].expectedTotalBytes, kTransparentImage.length);
}
}, skip: isBrowser);
test('NetworkImage is evicted from cache on SocketException', () async {
final MockHttpClient mockHttpClient = MockHttpClient();
when(mockHttpClient.getUrl(any)).thenAnswer((_) => throw const SocketException('test exception'));
debugNetworkImageHttpClientProvider = () => mockHttpClient;
final ImageProvider imageProvider = NetworkImage(nonconst('testing.url'));
expect(imageCache.pendingImageCount, 0);
expect(imageCache.statusForKey(imageProvider).untracked, true);
final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
expect(imageCache.pendingImageCount, 1);
expect(imageCache.statusForKey(imageProvider).pending, true);
final Completer<dynamic> caughtError = Completer<dynamic>();
result.addListener(ImageStreamListener(
(ImageInfo info, bool syncCall) {},
onError: (dynamic error, StackTrace stackTrace) {
caughtError.complete(error);
},
));
final dynamic err = await caughtError.future;
expect(err, isA<SocketException>());
expect(imageCache.pendingImageCount, 0);
expect(imageCache.statusForKey(imageProvider).untracked, true);
expect(imageCache.containsKey(result), isFalse);
debugNetworkImageHttpClientProvider = null;
}, skip: isBrowser); // Browser does not resolve images this way.
});
});
......
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