obtainKey method
- @override
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 ImageProviders 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 ==
).
Implementation
@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<Map<String, List<String>>>(_kAssetManifestFileName, _manifestParser).then<void>(
(Map<String, List<String>> manifest) {
final String chosenName = _chooseVariant(
keyName,
configuration,
manifest == null ? null : manifest[keyName]
);
final double chosenScale = _parseScale(chosenName);
final AssetBundleImageKey key = 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 = 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 = Completer<AssetBundleImageKey>();
return completer.future;
}