Remove network images from cache on any exception during loading (#53875)
* Remove network images from cache on any exception during loading
This commit is contained in:
parent
4e811d2819
commit
30738982b4
@ -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.
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user