# Adding ImageProvider.loadBuffer

> ImageProviders must now be implemented using the new loadBuffer API instead of the existing load API.




:::important
These breaking change docs are accurate, as of the release
under which they are published. Over time, the
workarounds described here might become inaccurate.
We don't, in general, keep these breaking change docs up
to date as of each release.

这些破坏性改动文档的准确性仅限于其发布时对应的版本。
随着时间的推移，文档中描述的方案可能会逐渐失效。
通常情况下，我们不会在每次发布新版本时都对这些文档进行同步更新。

The [breaking change index file](/release/breaking-changes)
lists the docs created for each release.

[破坏性改动列表](/release/breaking-changes) 
列出了每个版本的文档。

:::


## Summary

* `ImageProvider` now has a method called `loadBuffer` that functions
   similarly to `load`, except that it decodes from an `ui.ImmutableBuffer`.
* `ui.ImmutableBuffer` can now be created directly from an asset key.
* The `AssetBundle` classes can now load an `ui.ImmutableBuffer`.
* The `PaintingBinding` now has a method called
  `instantiateImageCodecFromBuffer`, which functions similarly to
  `instantiateImageCodec`.
* `ImageProvider.load` is now deprecated, it will be removed in a future
   release.
* `PaintingBinding.instantiateImageCodec` is now deprecated, it will be removed
   in a future release.

## Context

`ImageProvider.loadBuffer` is a new method that must be implemented in order to
load images. This API allows asset-based image loading to be performed faster
and with less memory impact on application.

## Description of change

When loading asset images, previously the image provider API required multiple
copies of the compressed data. First, when opening the asset the data was
copied into the external heap and exposed to Dart as a typed data array. Then
that typed data array was eventually converted into an `ui.ImmutableBuffer`,
which internally copies the data into a second structure for decoding.

With the addition of `ui.ImmutableBuffer.fromAsset`, compressed image bytes can
be loaded directly into the structure used for decoding. Using this approach
requires changes to the byte loading pipeline of `ImageProvider`. This process
is also faster, because it bypasses some additional scheduling overhead of the
previous method channel based loader.

`ImageProvider.loadBuffer` otherwise has the same contract as
`ImageProvider.load`, except it provides a new decoding callback that expects
an `ui.ImmutableBuffer` instead of a `Uint8List`. For `ImageProvider` classes
that acquire bytes from places other than assets, the convenience method
`ui.ImmutableBuffer.fromUint8List` can be used for compatibility.

## Migration guide

Classes that subclass `ImageProvider` must implement the `loadBuffer` method for
loading assets. Classes that delegate to or call the methods of an
`ImageProvider` directly must use `loadBuffer` instead of `load`.

Code before migration:

```dart
class MyImageProvider extends ImageProvider<MyImageProvider> {
  @override
  ImageStreamCompleter load(MyImageProvider key, DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(
        codec: _loadData(key, decode),
    );
  }

  Future<ui.Codec> _loadData(MyImageProvider key, DecoderCallback decode) async {
    final Uint8List bytes = await bytesFromSomeApi();
    return decode(bytes);
  }
}

class MyDelegatingProvider extends ImageProvider<MyDelegatingProvider> {
  MyDelegatingProvider(this.provider);

  final ImageProvider provider;

  @override
  ImageStreamCompleter load(MyDelegatingProvider key, DecoderCallback decode) {
    return provider.load(key, decode);
  }
}
```

Code after migration:

```dart
class MyImageProvider extends ImageProvider<MyImageProvider> {
  @override
  ImageStreamCompleter loadBuffer(MyImageProvider key, DecoderBufferCallback decode) {
    return MultiFrameImageStreamCompleter(
        codec: _loadData(key, decode),
    );
  }

  Future<ui.Codec> _loadData(MyImageProvider key, DecoderBufferCallback decode) async {
    final Uint8List bytes = await bytesFromSomeApi();
    final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
    return decode(buffer);
  }
}

class MyDelegatingProvider extends ImageProvider<MyDelegatingProvider> {
  MyDelegatingProvider(this.provider);

  final ImageProvider provider;

  @override
  ImageStreamCompleter loadBuffer(MyDelegatingProvider key, DecoderCallback decode) {
    return provider.loadBuffer(key, decode);
  }
}
```

In both cases you might choose to keep the
previous implementation of `ImageProvider.load`
to give users of your code time to migrate as well.

## Timeline

Landed in version: 3.1.0-0.0.pre.976<br>
In stable release: 3.3.0

## References

API documentation:

* [`ImmutableBuffer`](https://api.flutter-io.cn/flutter/dart-ui/ImmutableBuffer-class.html)
* [`ImageProvider`](https://api.flutter-io.cn/flutter/painting/ImageProvider-class.html)

Relevant PR:

* [Use immutable buffer for loading asset images](https://github.com/flutter/flutter/pull/103496)

