getOrBuildWithReport method

PictureCacheResult getOrBuildWithReport(
  1. String key,
  2. Size size,
  3. void builder(
    1. Canvas canvas,
    2. Size size
    )
)

Implementation

PictureCacheResult getOrBuildWithReport(
  String key,
  ui.Size size,
  void Function(ui.Canvas canvas, ui.Size size) builder,
) {
  final safeSize = _safeCacheSize(size);
  if (_isEmptySize(safeSize)) {
    invalidate(key);
    _misses++;
    _skippedWrites++;
    return PictureCacheResult(
      picture: _recordEmptyPicture(),
      cacheHit: false,
      retained: false,
      skippedWrite: true,
    );
  }

  final cached = _cache.remove(key);
  if (cached != null && cached.size == safeSize) {
    _hits++;
    _cache[key] = cached; // Move to end (MRU)
    return PictureCacheResult(
      picture: cached.picture,
      cacheHit: true,
      retained: true,
      skippedWrite: false,
    );
  }
  if (cached != null) {
    // The same logical layer at a different size must be re-recorded.
    cached.picture.dispose();
    _currentMemory = (_currentMemory - cached.memoryBytes)
        .clamp(0, _maxTrackedMemoryBytes)
        .toInt();
  }

  _misses++;
  final recorder = ui.PictureRecorder();
  final canvas = ui.Canvas(recorder);
  builder(canvas, safeSize);
  final picture = recorder.endRecording();

  // Estimate memory (RGBA pixels + ~2KB overhead).
  final estimatedBytes = estimateMemoryBytes(safeSize);
  if (!_canRetain(estimatedBytes)) {
    _skippedWrites++;
    return PictureCacheResult(
      picture: picture,
      cacheHit: false,
      retained: false,
      skippedWrite: true,
    );
  }

  _evictIfNeeded(estimatedBytes);

  _cache[key] = _CachedPicture(picture, estimatedBytes, safeSize);
  _currentMemory += estimatedBytes;
  return PictureCacheResult(
    picture: picture,
    cacheHit: false,
    retained: true,
    skippedWrite: false,
  );
}