resolveStreamForKey method

  1. @override
void resolveStreamForKey(
  1. ImageConfiguration configuration,
  2. ImageStream stream,
  3. T key,
  4. ImageErrorListener handleError
)
override

Called by resolve with the key returned by obtainKey.

Subclasses should override this method rather than calling obtainKey if they need to use a key directly. The resolve method installs appropriate error handling guards so that errors will bubble up to the right places in the framework, and passes those guards along to this method via the handleError parameter.

It is safe for the implementation of this method to call handleError multiple times if multiple errors occur, or if an error is thrown both synchronously into the current part of the stack and thrown into the enclosing Zone.

The default implementation uses the key to interact with the ImageCache, calling ImageCache.putIfAbsent and notifying listeners of the stream. Implementers that do not call super are expected to correctly use the ImageCache.

Implementation

@override
void resolveStreamForKey(
  ImageConfiguration configuration,
  ImageStream stream,
  T key,
  ImageErrorListener handleError,
) {
  // Something managed to complete the stream, or it's already in the image
  // cache. Notify the wrapped provider and expect it to behave by not
  // reloading the image since it's already resolved.
  // Do this even if the context has gone out of the tree, since it will
  // update LRU information about the cache. Even though we never showed the
  // image, it was still touched more recently.
  // Do this before checking scrolling, so that if the bytes are available we
  // render them even though we're scrolling fast - there's no additional
  // allocations to do for texture memory, it's already there.
  if (stream.completer != null || PaintingBinding.instance.imageCache.containsKey(key)) {
    imageProvider.resolveStreamForKey(configuration, stream, key, handleError);
    return;
  }
  // The context has gone out of the tree - ignore it.
  if (context.context == null) {
    return;
  }
  // Something still wants this image, but check if the context is scrolling
  // too fast before scheduling work that might never show on screen.
  // Try to get to end of the frame callbacks of the next frame, and then
  // check again.
  if (Scrollable.recommendDeferredLoadingForContext(context.context!)) {
    SchedulerBinding.instance.scheduleFrameCallback((_) {
      scheduleMicrotask(() => resolveStreamForKey(configuration, stream, key, handleError));
    });
    return;
  }
  // We are in the tree, we're not scrolling too fast, the cache doesn't
  // have our image, and no one has otherwise completed the stream. Go.
  imageProvider.resolveStreamForKey(configuration, stream, key, handleError);
}