Skip to main content

新增 ImageProvider.loadBuffer

ImageProvider 現在必須使用新的 loadBuffer API 來實作, 而非既有的 load API。

摘要

#
  • ImageProvider 現在新增了一個名為 loadBuffer 的方法,其功能 與 load 類似,但它是從 ui.ImmutableBuffer 進行解碼。
  • ui.ImmutableBuffer 現在可以直接從資源鍵建立。
  • AssetBundle 類別現在可以載入 ui.ImmutableBuffer
  • PaintingBinding 現在新增了一個名為 instantiateImageCodecFromBuffer 的方法,其功能與 instantiateImageCodec 類似。
  • ImageProvider.load 現已被棄用,未來版本將會移除。
  • PaintingBinding.instantiateImageCodec 現已被棄用,未來版本 也將會移除。

背景說明

#

ImageProvider.loadBuffer 是一個新的方法,必須實作以載入圖片。此 API 讓基於資源的圖片載入能更快速, 並減少對應用程式的記憶體影響。

變更說明

#

過去在載入資源圖片時,image provider API 會產生多份壓縮資料的複本。首先,當開啟資源時, 資料會被複製到外部堆積(external heap),並以型別化資料陣列(typed data array)的形式暴露給 Dart。接著, 該型別化資料陣列最終會被轉換為 ui.ImmutableBuffer, 而這個過程會在內部將資料再複製到另一個結構中以進行解碼。

隨著 ui.ImmutableBuffer.fromAsset 的加入,壓縮圖片位元組現在可以直接載入到用於解碼的結構中。這種做法 需要對 ImageProvider 的位元組載入流程進行調整。這個流程也更快, 因為它繞過了舊有基於 method channel 載入器的額外排程開銷。

ImageProvider.loadBuffer 的合約與 ImageProvider.load 基本相同,但它提供了一個新的解碼回呼(callback),該回呼期望接收 ui.ImmutableBuffer 而非 Uint8List。對於從非資源來源取得位元組的 ImageProvider 類別, 可以使用便利方法 ui.ImmutableBuffer.fromUint8List 以確保相容性。

遷移指南

#

繼承自 ImageProvider 的類別,必須實作 loadBuffer 方法以載入資源。 直接委派或呼叫 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 ImageProvider 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 ImageProvider 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: