"Fossies" - the Fresh Open Source Software Archive

Member "flutter-1.22.4/packages/flutter/lib/src/widgets/scroll_aware_image_provider.dart" (13 Nov 2020, 5072 Bytes) of package /linux/misc/flutter-1.22.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Dart source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2014 The Flutter Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style license that can be
    3 // found in the LICENSE file.
    4 
    5 // @dart = 2.8
    6 
    7 import 'dart:async';
    8 
    9 import 'package:flutter/painting.dart';
   10 import 'package:flutter/scheduler.dart';
   11 
   12 import 'disposable_build_context.dart';
   13 import 'framework.dart';
   14 import 'scrollable.dart';
   15 
   16 /// An [ImageProvider] that makes use of
   17 /// [Scrollable.recommendDeferredLoadingForContext] to avoid loading images when
   18 /// rapidly scrolling.
   19 ///
   20 /// This provider assumes that its wrapped [imageProvider] correctly uses the
   21 /// [ImageCache], and does not attempt to re-acquire or decode images in the
   22 /// cache.
   23 ///
   24 /// Calling [resolve] on this provider will cause it to obtain the image key
   25 /// and then check the following:
   26 ///
   27 ///   1. If the returned [ImageStream] has been completed, end. This can happen
   28 ///      if the caller sets the completer on the stream.
   29 ///   2. If the [ImageCache] has a completer for the key for this image, ask the
   30 ///      wrapped provider to resolve.
   31 ///      This can happen if the image was precached, or another [ImageProvider]
   32 ///      already resolved the same image.
   33 ///   3. If the [context] has been disposed, end. This can happen if the caller
   34 ///      has been disposed and is no longer interested in resolving the image.
   35 ///   4. If the widget is scrolling with high velocity at this point in time,
   36 ///      wait until the beginning of the next frame and go back to step 1.
   37 ///   5. Delegate loading the image to the wrapped provider and finish.
   38 ///
   39 /// If the cycle ends at steps 1 or 3, the [ImageStream] will never be marked as
   40 /// complete and listeners will not be notified.
   41 ///
   42 /// The [Image] widget wraps its incoming providers with this provider to avoid
   43 /// overutilization of resources for images that would never appear on screen or
   44 /// only be visible for a very brief period.
   45 @optionalTypeArgs
   46 class ScrollAwareImageProvider<T> extends ImageProvider<T> {
   47   /// Creates a [ScrollAwareImageProvider].
   48   ///
   49   /// The [context] object is the [BuildContext] of the [State] using this
   50   /// provider. It is used to determine scrolling velocity during [resolve]. It
   51   /// must not be null.
   52   ///
   53   /// The [imageProvider] is used to create a key and load the image. It must
   54   /// not be null, and is assumed to interact with the cache in the normal way
   55   /// that [ImageProvider.resolveStreamForKey] does.
   56   const ScrollAwareImageProvider({
   57     @required this.context,
   58     @required this.imageProvider,
   59   }) : assert(context != null),
   60        assert(imageProvider != null);
   61 
   62   /// The context that may or may not be enclosed by a [Scrollable].
   63   ///
   64   /// Once [DisposableBuildContext.dispose] is called on this context,
   65   /// the provider will stop trying to resolve the image if it has not already
   66   /// been resolved.
   67   final DisposableBuildContext context;
   68 
   69   /// The wrapped image provider to delegate [obtainKey] and [load] to.
   70   final ImageProvider<T> imageProvider;
   71 
   72   @override
   73   void resolveStreamForKey(
   74     ImageConfiguration configuration,
   75     ImageStream stream,
   76     T key,
   77     ImageErrorListener handleError,
   78   ) {
   79     // Something managed to complete the stream, or it's already in the image
   80     // cache. Notify the wrapped provider and expect it to behave by not
   81     // reloading the image since it's already resolved.
   82     // Do this even if the context has gone out of the tree, since it will
   83     // update LRU information about the cache. Even though we never showed the
   84     // image, it was still touched more recently.
   85     // Do this before checking scrolling, so that if the bytes are available we
   86     // render them even though we're scrolling fast - there's no additional
   87     // allocations to do for texture memory, it's already there.
   88     if (stream.completer != null || PaintingBinding.instance.imageCache.containsKey(key)) {
   89       imageProvider.resolveStreamForKey(configuration, stream, key, handleError);
   90       return;
   91     }
   92     // The context has gone out of the tree - ignore it.
   93     if (context.context == null) {
   94       return;
   95     }
   96     // Something still wants this image, but check if the context is scrolling
   97     // too fast before scheduling work that might never show on screen.
   98     // Try to get to end of the frame callbacks of the next frame, and then
   99     // check again.
  100     if (Scrollable.recommendDeferredLoadingForContext(context.context)) {
  101         SchedulerBinding.instance.scheduleFrameCallback((_) {
  102           scheduleMicrotask(() => resolveStreamForKey(configuration, stream, key, handleError));
  103         });
  104         return;
  105     }
  106     // We are in the tree, we're not scrolling too fast, the cache doesn't
  107     // have our image, and no one has otherwise completed the stream.  Go.
  108     imageProvider.resolveStreamForKey(configuration, stream, key, handleError);
  109   }
  110 
  111   @override
  112   ImageStreamCompleter load(T key, DecoderCallback decode) => imageProvider.load(key, decode);
  113 
  114   @override
  115   Future<T> obtainKey(ImageConfiguration configuration) => imageProvider.obtainKey(configuration);
  116 }