download:C#速成指南:从入门到进阶,实战WPF与Unity3D开发

备链:https://www.97yrbl.com/t-1374.html

新的计划

咱们奇妙地将 FFi 计划与外接纹理计划组合,解决了一系列业务痛点。

FFI
正如结尾说的那些问题,Texture 计划有些做不到的事件,这须要其余计划来互补,这其中外围须要的就是 ui.Image。咱们把 native 内存地址、长度等信息传递给 flutter 侧,用于生成 ui.Image。

首先 native 侧先获取必要的参数(以 iOS 为例):

_rowBytes = CGImageGetBytesPerRow(cgImage);CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);CFDataRef rawDataRef = CGDataProviderCopyData(dataProvider);_handle = (long)CFDataGetBytePtr(rawDataRef);NSData *data = CFBridgingRelease(rawDataRef);self.data = data;_length = data.length;dart 侧拿到后,@override  FutureOr<ImageInfo> createImageInfo(Map map) {Completer<ImageInfo> completer = Completer<ImageInfo>();int handle = map['handle'];int length = map['length'];int width = map['width'];int height = map['height'];int rowBytes = map['rowBytes'];ui.PixelFormat pixelFormat =    ui.PixelFormat.values[map['flutterPixelFormat'] ?? 0];Pointer<Uint8> pointer = Pointer<Uint8>.fromAddress(handle);Uint8List pixels = pointer.asTypedList(length);ui.decodeImageFromPixels(pixels, width, height, pixelFormat,    (ui.Image image) {  ImageInfo imageInfo = ImageInfo(image: image);  completer.complete(imageInfo);  //开释 native 内存  PowerImageLoader.instance.releaseImageRequest(options);}, rowBytes: rowBytes);return completer.future;  }

咱们能够通过 ffi 拿到 native 内存,从而生成 ui.Image。这里有个问题,尽管通过 ffi 能间接获取 native 内存,然而因为 decodeImageFromPixels 会有内存拷贝,在拷贝解码后的图片数据时,内存峰值会更加重大。

这里有两个优化方向:

解码前的图片数据给 flutter,由 flutter 提供的解码器解码,从而削减内存拷贝峰值;
与 flutter 官网探讨,尝试从外部缩小这次内存拷贝。
FFI 这种形式适宜轻度应用、非凡场景应用,反对这种形式能够解决无奈获取 ui.Image 的问题,也能够在模拟器上展现图片(flutter <= 1.23.0-18.1.pre),并且图片缓存将齐全交给 ImageCache 治理。

Texture
Texture 计划与原生联合有一些难度,这里波及到没有 ui.Image 只有 textureId。这里有几个问题须要解决:

问题一:Image Widget 须要 ui.Image 去 build RawImage 从而绘制,这在本文后面的Flutter 原生计划介绍中也提到了。

问题二:ImageCache 依赖 ImageInfoui.Image 的宽高进行 cache 大小计算以及缓存前的校验。

问题三:native 侧 texture 生命周期治理

都有解决方案:

问题一:通过自定义 Image 解决,透出 imageBuilder 来让内部自定义图片 widget

问题二:为 Texture 自定义 ui.image,如下:

import 'dart:typed_data';import 'dart:ui' as ui show Image;import 'dart:ui';class TextureImage implements ui.Image {  int _width;  int _height;  int textureId;  TextureImage(this.textureId, int width, int height)      : _width = width,        _height = height;  @override  void dispose() {    // TODO: implement dispose  }  @override  int get height => _height;  @override  Future<ByteData> toByteData(      {ImageByteFormat format = ImageByteFormat.rawRgba}) {    // TODO: implement toByteData    throw UnimplementedError();  }