- override
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 operator ==
).
Source
@override Future<AssetBundleImageKey> obtainKey(ImageConfiguration configuration) { // This function tries to return a SynchronousFuture if possible. We do this // because otherwise showing an image would always take at least one frame, // which would be sad. (This code is called from inside build/layout/paint, // which all happens in one call frame; using native Futures would guarantee // that we resolve each future in a new call frame, and thus not in this // build/layout/paint sequence.) final AssetBundle chosenBundle = bundle ?? configuration.bundle ?? rootBundle; Completer<AssetBundleImageKey> completer; Future<AssetBundleImageKey> result; chosenBundle.loadStructuredData(_kAssetManifestFileName, _manifestParser).then( (Map<String, List<String>> manifest) { final String chosenName = _chooseVariant( name, configuration, manifest == null ? null : manifest[name] ); final double chosenScale = _parseScale(chosenName); final AssetBundleImageKey key = new AssetBundleImageKey( bundle: chosenBundle, name: chosenName, scale: chosenScale ); if (completer != null) { // We already returned from this function, which means we are in the // asynchronous mode. Pass the value to the completer. The completer's // future is what we returned. completer.complete(key); } else { // We haven't yet returned, so we must have been called synchronously // just after loadStructuredData returned (which means it provided us // with a SynchronousFuture). Let's return a SynchronousFuture // ourselves. result = new SynchronousFuture<AssetBundleImageKey>(key); } } ).catchError((dynamic error, StackTrace stack) { // We had an error. (This guarantees we weren't called synchronously.) // Forward the error to the caller. assert(completer != null); assert(result == null); completer.completeError(error, stack); }); if (result != null) { // The code above ran synchronously, and came up with an answer. // Return the SynchronousFuture that we created above. return result; } // The code above hasn't yet run its "then" handler yet. Let's prepare a // completer for it to use when it does run. completer = new Completer<AssetBundleImageKey>(); return completer.future; }