preCache static method

Future<FileInfo> preCache({
  1. required String imageUrl,
  2. String? cacheKey,
  3. Map<String, String>? headers,
  4. BaseCacheManager? cacheManager,
  5. int? maxWidthDiskCache,
  6. int? maxHeightDiskCache,
  7. Duration? timeout,
})

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;
}