preCache static method
Downloads and caches an image without rendering it.
Use this to warm the cache before the image is needed on screen.
When maxWidthDiskCache or maxHeightDiskCache are provided and the
cacheManager supports ImageCacheManager, the resized variant is
cached.
Waits for the cache manager to finish refreshing an expired cache entry before returning. If the refresh fails and only the stale cached file remains, this throws a StateError rather than returning that stale file as if it were success.
timeout, if given, is applied between events on the underlying
stream via Stream.timeout and throws a TimeoutException when
exceeded. It unblocks the caller but does not cancel the in-flight
download.
Implementation
static Future<FileInfo> preCache({
required String imageUrl,
String? cacheKey,
Map<String, String>? headers,
BaseCacheManager? cacheManager,
int? maxWidthDiskCache,
int? maxHeightDiskCache,
Duration? timeout,
}) async {
final cm = _effectiveCacheManager(cacheManager);
if (cm is! ImageCacheManager &&
(maxWidthDiskCache != null || maxHeightDiskCache != null)) {
throw ArgumentError(
'To resize the image the CacheManager needs to be an '
'ImageCacheManager. maxWidthDiskCache and maxHeightDiskCache will '
'be ignored when a normal CacheManager is used.',
);
}
Stream<FileResponse> stream;
if (cm is ImageCacheManager &&
(maxWidthDiskCache != null || maxHeightDiskCache != null)) {
stream = cm.getImageFile(
imageUrl,
key: cacheKey,
headers: headers,
maxWidth: maxWidthDiskCache,
maxHeight: maxHeightDiskCache,
);
} else {
stream = cm.getFileStream(
imageUrl,
key: cacheKey,
headers: headers,
);
}
if (timeout != null) {
stream = stream.timeout(timeout);
}
// Drain the entire stream and return the last FileInfo. This ensures
// that when the cache manager yields a stale entry followed by a
// refreshed one, we wait for the refresh to complete.
FileInfo? result;
await for (final response in stream) {
if (response is FileInfo) result = response;
}
if (result == null) {
throw StateError('Cache manager completed without providing a file');
}
// A successful refresh always yields a FileInfo sourced from the
// network (see DefaultCacheManager._downloadFile), so a Cache-sourced
// result that is still expired means the refresh silently failed.
if (result.source == FileSource.Cache &&
result.validTill.isBefore(DateTime.now())) {
throw StateError(
'preCache failed to refresh $imageUrl: the cache manager only '
'returned a stale cached file.',
);
}
return result;
}