概述

#
  • ImageProvider 现在有一个名为 loadBuffer 的方法,其功能与 load 类似,不同之处在于它从 ui.ImmutableBuffer 进行解码。
  • ui.ImmutableBuffer 现在可以直接从 asset key 创建。
  • AssetBundle 类现在可以加载 ui.ImmutableBuffer
  • PaintingBinding 现在有一个名为 instantiateImageCodecFromBuffer 的方法,其功能与 instantiateImageCodec 类似。
  • ImageProvider.load 现已弃用,将在未来的版本中移除。
  • PaintingBinding.instantiateImageCodec 现已弃用,将在未来的版本中移除。

背景

#

ImageProvider.loadBuffer 是一个必须实现的新方法,用于加载图像。此 API 允许基于 asset 的图像加载更快进行,并对应用程序的内存影响更小。

变更说明

#

在加载 asset 图像时,以前的图像提供程序 API 需要压缩数据的多个副本。首先,在打开 asset 时,数据被复制到外部堆并作为类型化数据数组暴露给 Dart。然后,该类型化数据数组最终被转换为 ui.ImmutableBuffer,后者在内部将数据复制到第二个结构中进行解码。

随着 ui.ImmutableBuffer.fromAsset 的添加,压缩图像字节可以直接加载到用于解码的结构中。使用这种方法需要更改 ImageProvider 的字节加载管道。此过程也更快,因为它绕过了以前基于方法通道的加载器的一些额外调度开销。

ImageProvider.loadBuffer 否则与 ImageProvider.load 具有相同的约定,不同之处在于它提供了一个新的解码回调,该回调期望 ui.ImmutableBuffer 而不是 Uint8List。对于从非 asset 位置获取字节的 ImageProvider 类,可以使用便捷方法 ui.ImmutableBuffer.fromUint8List 来确保兼容性。

迁移指南

#

子类化 ImageProvider 的类必须实现 loadBuffer 方法来加载 asset。直接委托或调用 ImageProvider 方法的类必须使用 loadBuffer 而不是 load

迁移前的代码

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 ImageProvder provider;

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

迁移后的代码

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 ImageProvder provider;

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

在这两种情况下,您都可以选择保留 ImageProvider.load 的先前实现,以便为您的代码用户提供迁移时间。

时间线

#

已在版本中发布: 3.1.0-0.0.pre.976
在稳定版本中: 3.3.0

参考资料

#

API 文档

相关 PR