Loading network pictures
()
is a method provided by Flutter to load images from the network, which can load images from a specified URL and display them in the application after loading is complete. In this section, we will discuss the loading process of the image based on the source code.
ImageProvider
ImageProvider
It is an abstract class in Flutter. It defines a common interface for loading pictures, which can be used to load local pictures, network pictures and other types of pictures.
ImageProvider
The class contains two core methods:obtainKey
andloadBuffer
。
resolve
/// Resolves this image provider using the given `configuration`, returning /// an [ImageStream]. /// /// This is the public entry-point of the [ImageProvider] class hierarchy. /// /// Subclasses should implement [obtainKey] and [load], which are used by this /// method. If they need to change the implementation of [ImageStream] used, /// they should override [createStream]. If they need to manage the actual /// resolution of the image, they should override [resolveStreamForKey]. /// /// See the Lifecycle documentation on [ImageProvider] for more information. @nonVirtual ImageStream resolve(ImageConfiguration configuration) { assert(configuration != null); final ImageStream stream = createStream(configuration); // Load the key (potentially asynchronously), set up an error handling zone, // and call resolveStreamForKey. _createErrorHandlerAndKey( configuration, (T key, ImageErrorListener errorHandler) { resolveStreamForKey(configuration, stream, key, errorHandler); }, (T? key, Object exception, StackTrace? stack) async { await null; // wait an event turn in case a listener has been added to the image stream. InformationCollector? collector; assert(() { collector = () => <DiagnosticsNode>[ DiagnosticsProperty<ImageProvider>('Image provider', this), DiagnosticsProperty<ImageConfiguration>('Image configuration', configuration), DiagnosticsProperty<T>('Image key', key, defaultValue: null), ]; return true; }()); if ( == null) { (_ErrorImageCompleter()); } !.reportError( exception: exception, stack: stack, context: ErrorDescription('while resolving an image'), silent: true, // could be a network error or whatnot informationCollector: collector, ); }, ); return stream; }
According to the documentation, we can learn the following:
1. Use the given `configuration` to parse the image provider and return a [ImageStream].
2. This is the public entry point of the [ImageProvider] class hierarchy.
3. Subclasses should implement the [obtainKey] and [load] methods, and these two methods will be used by this method.
4. If the subclass needs to change the implementation of [ImageStream] used, the [createStream] method should be overridden.
5. If the subclass needs to manage the actual image resolution, the [resolveStreamForKey] method should be overridden.
readresolve
Implementation of the method. We can know:
1. It uses the givenconfiguration
Create a parameterImageStream
Object(createStream
). Then call_createErrorHandlerAndKey
Method, This method will asynchronously obtain the unique identifier of the image and set an error handling area to prevent errors from occurring during the image loading process.
2. If an exception occurs during the process of obtaining a unique identifier, the error message will be encapsulated into one_ErrorImageCompleter
object, and set it toImageStream
ofcompleter
Attribute, indicating that the image has failed to load.
3. If the unique identifier is successfully obtained, it will be calledresolveStreamForKey
Method to parse pictures and store picture data toImageStream
In the object, for subsequent use.
4. This method isImageProvider
The common entry point of the class hierarchy, as it is the parsing method for all image providers. Subclasses only need to be implementedobtainKey
andload
Method to get the unique identifier of the image and load the image data without rewritingresolve
method.
5. If the subclass needs to be changedImageStream
The implementation method can be rewrittencreateStream
method. If the subclass needs to manage the actual image resolution, it can be rewritedresolveStreamForKey
method. For example,AssetImage
In the classcreateStream
Method returns aAssetBundleImageStreamCompleter
Object, which is used to load image data from application resources. andNetworkImage
In the classresolveStreamForKey
Methods Use HTTP client to load image data from the network.
6. There is also some debugging information in this code, such as adding image providers, image configurations, and image unique identifiers to the debugging information to debug when an error occurs.
obtainKey
/// Converts an ImageProvider's settings plus an ImageConfiguration to a key /// that describes the precise image to load. /// /// The type of the key is determined by the subclass. It is a value that /// unambiguously identifies the image (_including its scale_) that the [load] /// method will fetch. Different [ImageProvider]s given the same constructor /// arguments and [ImageConfiguration] objects should return keys that are /// '==' to each other (possibly by using a class for the key that itself /// implements [==]). Future<T> obtainKey(ImageConfiguration configuration);
This comment is aboutobtainKey
Description of the method. This method isImageProvider
One of the methods that should be implemented by subclassing theImageProvider
Settings andImageConfiguration
Convert to a uniquely identifiable imagekey
。
DifferentImageProvider
According to the same constructor parameters andImageConfiguration
The object should return equalkey
, to facilitate subsequent loading and cache images.key
The type of ,is determined by the subclass, should be a value that uniquely identifies the image to be loaded (including its scaling).
In realizingobtainKey
When a method is used, subclasses can consider using custom classes to represent them.key
, and implement==
Method to ensure uniqueness.
resolveStreamForKey
@protected void resolveStreamForKey(ImageConfiguration configuration, ImageStream stream, T key, ImageErrorListener handleError) { // This is an unusual edge case where someone has told us that they found // the image we want before getting to this method. We should avoid calling // load again, but still update the image cache with LRU information. if ( != null) { final ImageStreamCompleter? completer = ( key, () => !, onError: handleError, ); assert(identical(completer, )); return; } final ImageStreamCompleter? completer = ( key, /// load () => loadBuffer(key, ), onError: handleError, ); if (completer != null) { /// The key is to parse and set the ImageStreamCompleter object (completer); } }
Official documentation explanation:
- This method is
ImageProvider
One of the methods that should be implemented by subclasses ofkey
To parse the picture. -
resolveStreamForKey
The method is fromresolve
The parameters of the method call includeImageConfiguration
、ImageStream
、key
anderrorHandler
. Subclasses can be implementedresolveStreamForKey
Methods to manage the actual parsing process of images, and can also be callederrorHandler
To handle errors that may occur during parsing. - accomplish
resolveStreamForKey
When using a method, subclasses can consider usingkey
andImageCache
Interaction, such as callingMethod and
stream
Notify the listener. The default implementation has been usedkey
andImageCache
Interaction, subclasses can choose to callMethod or not called.
From the above source code, we can know the following points:
- 1. If
stream
The object already existscompleter
(that is, there is already a way to load the picture), thencompleter
Add toImageCache
, implement the cache function and return directly. - 2. If
stream
There is no object yetcompleter
, then callloadBuffer
Method loads the image and returns itImageStreamCompleter
Object added toImageCache
and set tostream
The object'scompleter
middle. - 3. If
loadBuffer
If an exception occurs in the method, the exception will be handed over toonError
Callback processing so that detailed error information can be provided during exception handling. - 4. The key is to parse and set up
ImageStreamCompleter
Object - 5、
The method internally
ImageStreamListener
Object added toImageStreamCompleter
The object's_listeners
The array is in.
( key, () => loadBuffer(key, ), onError: handleError, )
loadBuffer
/// Converts a key into an [ImageStreamCompleter], and begins fetching the /// image. /// /// For backwards-compatibility the default implementation of this method calls /// through to []. However, implementors of this interface should /// only override this method and not [], which is deprecated. /// /// The [decode] callback provides the logic to obtain the codec for the /// image. /// /// See also: /// /// * [ResizeImage], for modifying the key to account for cache dimensions. @protected ImageStreamCompleter loadBuffer(T key, DecoderBufferCallback decode) { return load(key, ); }
From the source code, we know that[], which is deprecated
Abandoned. Subclasses only need to be rewriteloadBuffer
Just the method.
- This method is a protected method of ImageProvider, which is used to load the specified image from the cache.
- It accepts two parameters: one is the key that uniquely identifies the image, and the other is a callback function decode used to decode the image data.
- This method calls the load method and returns an ImageStreamCompleter object, which represents a data stream during loading.
- In the load method, the incoming decode callback function is used to obtain image data from the cache or network and decode it, and then the decoded image data is passed to the ImageStreamCompleter object so that it can generate an ImageInfo object with the correct image data, which can be passed into the Image widget for displaying the image.
load(deprecated)
/// Converts a key into an [ImageStreamCompleter], and begins fetching the /// image. /// /// This method is deprecated. Implement [loadBuffer] for faster image /// loading. Only one of [load] and [loadBuffer] must be implemented, and /// [loadBuffer] is preferred. /// /// The [decode] callback provides the logic to obtain the codec for the /// image. /// /// See also: /// /// * [ResizeImage], for modifying the key to account for cache dimensions. @protected @Deprecated( 'Implement loadBuffer for faster image loading. ' 'This feature was deprecated after v2.13.0-1..', ) ImageStreamCompleter load(T key, DecoderCallback decode) { throw UnsupportedError('Implement loadBuffer for faster image loading'); }
From the comments, we can see:
This method has been abandoned and is no longer recommended for use. If you need faster image loading, implement the [loadBuffer] method. Only one of them is required in the [load] and [loadBuffer] methods, and [loadBuffer] is more recommended.
[decode] Callback provides the logic for getting the image codec.
evict
/// Evicts an entry from the image cache. /// /// Returns a [Future] which indicates whether the value was successfully /// removed. /// /// The [ImageProvider] used does not need to be the same instance that was /// passed to an [Image] widget, but it does need to create a key which is /// equal to one. /// /// The [cache] is optional and defaults to the global image cache. /// /// The [configuration] is optional and defaults to /// []. /// /// {@tool snippet} /// /// The following sample code shows how an image loaded using the [Image] /// widget can be evicted using a [NetworkImage] with a matching URL. /// /// ```dart /// class MyWidget extends StatelessWidget { /// const MyWidget({ /// , /// = ' ... ', /// }); /// /// final String url; /// /// @override /// Widget build(BuildContext context) { /// return (url); /// } /// /// void evictImage() { /// final NetworkImage provider = NetworkImage(url); /// ().then<void>((bool success) { /// if (success) { /// debugPrint('removed image!'); /// } /// }); /// } /// } /// ``` /// {@end-tool} Future<bool> evict({ ImageCache? cache, ImageConfiguration configuration = }) async { cache ??= imageCache; final T key = await obtainKey(configuration); return (key); }
This is a namedevict
The asynchronous method of , which is used to delete the image in a given configuration from the image cache. It has two optional parameters:cache
andconfiguration
. ifcache
The parameter is null, and the global one is used by default.imageCache
。configuration
The parameter is an image configuration that gets the key value of the image to be deleted from the cache. This method returns aFuture<bool>
Object, indicating whether the deletion is successful. If no image to be deleted is found in the cache, returnfalse
。
When the list slides quickly, you can use this method to do something when the memory skyrockets.
Summarize
ImageProvider
is an abstract class in Flutter that provides image data. It defines how to obtain image data from different data sources (such as file system, network, memory) and convert it intoImageStreamCompleter
Object, forImage
Component use.
In Flutter, useImage
Components to load and display images need to provide aImageProvider
Object as itsimage
The value of the attribute.ImageProvider
The class contains two key methods:obtainKey
andload
。
obtainKey
Method is used to obtain a uniquely identified image dataImageProvider
Object, This object can be used to cache image data so that it can be quickly retrieved when the image needs to be reloaded. For example,AssetImage
The class uses the path of the image resource as itsImageProvider
The identifier of the object so that it can be quickly retrieved from the memory or disk cache when it needs to be reloaded.
load
Method is used to obtain aImageStreamCompleter
Object, which contains image data used to draw an image. Before Flutter 2.5,load
A method is an abstract method that must be implemented by a subclass. But starting with Flutter 2.5,load
The method has been abandoned and replaced byresolve
method.resolve
Method accepts aImageConfiguration
parameter and return aFuture<ImageStreamCompleter>
Object. It's withload
The functions of the method are similar, both are used to obtain image data and convert it intoImageStreamCompleter
Object, forImage
Component use.
useImageProvider
The process of class loading and displaying images is as follows:
- Create a
ImageProvider
Object, which provides the source and identifier of image data. - use
ImageProvider
Object asImage
Componentimage
The value of the attribute. -
Image
The component will callobtainKey
Method to obtain a uniquely identified image dataImageProvider
Object. -
Image
The component will callresolve
Method to get oneFuture<ImageStreamCompleter>
Object. - When the image data is loaded,
ImageStreamCompleter
The object will notify it toImage
Components,Image
The component renders it to the screen.
Overall,ImageProvider
Classes are a very important class in Flutter, which provides a convenient way to load and display images. Althoughload
The method has been abandoned, butresolve
Methods provide better alternatives that can be used to acquire image data and convert it intoImageStreamCompleter
Object.
Reference link
Analysis of network image loading process of Flutter system_Android
Flutter Introduction Series (IV) ---Flutter Picture Cache
Flutter | Image Source code analysis and optimization method
Confused answer
When the picture is loaded for the first time,stream
Objects usually have nocompleter
. On the first callresolveStreamForKey
When thestream
The object'scompleter
and correspondingImageCache
ofImageStreamCompleter
Make binding, andcompleter
Will be set toImageStreamCompleter
。
The above is the detailed analysis of the ImageProvider source code example of Flutter loading image process. For more information about Flutter loading image ImageProvider, please follow my other related articles!