loadStructuredBinaryData<T> method

  1. @override
Future<T> loadStructuredBinaryData<T>(
  1. String key,
  2. FutureOr<T> parser(
    1. ByteData data
    )
)
override

Retrieve bytedata from the asset bundle, parse it with the given function, and return the function's result.

The result of parsing the bytedata is cached (the bytedata itself is not). For any given key, the parser is only run the first time.

Once the value has been successfully parsed, the future returned by this function for subsequent calls will be a SynchronousFuture, which resolves its callback synchronously.

Failures are not cached, and are returned as Futures with errors.

Implementation

@override
Future<T> loadStructuredBinaryData<T>(String key, FutureOr<T> Function(ByteData data) parser) {
  if (_structuredBinaryDataCache.containsKey(key)) {
    return _structuredBinaryDataCache[key]! as Future<T>;
  }
  // load can return a SynchronousFuture in certain cases, like in the
  // flutter_test framework. So, we need to support both async and sync flows.
  Completer<T>? completer; // For async flow.
  Future<T>? synchronousResult; // For sync flow.
  load(key).then<T>(parser).then<void>((T value) {
    synchronousResult = SynchronousFuture<T>(value);
    _structuredBinaryDataCache[key] = synchronousResult!;
    if (completer != null) {
      // The load and parse operation ran asynchronously. We already returned
      // from the loadStructuredBinaryData function and therefore the caller
      // was given the future of the completer.
      completer.complete(value);
    }
  }, onError: (Object error, StackTrace stack) {
    assert(completer != null, 'unexpected synchronous failure');
    // Either loading or parsing failed. We must report the error back to the
    // caller and anyone waiting on this call. We clear the cache for this
    // key, however, because we want future attempts to try again.
    _structuredBinaryDataCache.remove(key);
    completer!.completeError(error, stack);
  });
  if (synchronousResult != null) {
    // The above code ran synchronously. We can synchronously return the result.
    return synchronousResult!;
  }
  // Since the above code is being run asynchronously and thus hasn't run its
  // `then` handler yet, we'll return a completer that will be completed
  // when the handler does run.
  completer = Completer<T>();
  _structuredBinaryDataCache[key] = completer.future;
  return completer.future;
}