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 治理。
TextureTexture
计划与原生联合有一些难度,这里波及到没有 ui.Image
只有 textureId。这里有几个问题须要解决:
问题一:Image Widget 须要 ui.Image 去 build RawImage
从而绘制,这在本文后面的 Flutter 原生计划介绍中也提到了。
问题二:ImageCache
依赖 ImageInfo
中 ui.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();}