接上篇:https://developer.aliyun.com/article/1225988?spm=a2c6h.13148508.setting.15.2f394f0e7JCBdO
五、 整体架构
我们将两种解决方案非常优雅地结合在了一起:
我们抽象出了PowerImageProvider,对于external(ffi)、texture,分别生产自己的ImageInfo即可。它将通过对PowerImageLoader的调用,提供统一的加载与释放能力。
蓝色实线的ImageExt即为自定义的Image Widget,为texture方式透出了imageBuilder。
蓝色虚线ImageCacheExt即为ImageCache的扩展,仅在flutter <2.2.0版本才需要,它将提供ImageCache释放时机的回调。
这次,我们也设计了超强的扩展能力。除了支持网络图、本地图、flutter资源、native资源外,我们提供了自定义图片类型的通道,flutter可以传递任何自定义的参数组合给native,只要native注册对应类型loader,比如「相册」这种场景,使用方可以自定义imageType为album,native使用自己的逻辑进行加载图片。有了这个自定义通道,甚至图片滤镜都可以使用PowerImage进行展示刷新。
除了图片类型的扩展,渲染类型也可进行自定义。比如在上面ffi中说的,为了降低内存拷贝带来的峰值问题,使用方可以在flutter侧进行解码,当然这需要native图片库提供解码前的数据。
六、 数据
1. FFI vs Texture
• 机型:iPhone 11 Pro;
• 图片:300张网络图;
• 行为:在listView中手动滚动到底部再滚动到顶部;
• native Cache:20 maxMemoryCount;
• flutter Cache:30MB
• flutter version 2.5.3;
• release模式下
这里有两个现象:
• FFI:186MB波动
• Texture:194MB波动
在2.5.3版本中,Texture方案与FFI,在内存水位上差异不大,内存波动上面与flutter 1.22结论相反。
图中棋格图,为打开checkerboardRasterCacheImages后所展示,可以看出,FFI方案会缓存整个cell,而Texture方案,只有cell中的文字被缓存,RasterCache会使得FFI在流畅度方面会有一定优势。
2. 滚动流畅性分析
• 设备:Android OnePlus 8t,CPU和GPU进行了锁频。
• Case:GridView每行4张图片,300张图片,从上往下,再从下往上,滑动幅度从500,1000,1500,2000,2500,5轮滑动。重复20次。
• 方式:for i in {1..20}; do flutter drive --target=test_driver/app.dart –profile;done跑数据,获取TimeLine数据并分析。
结论:
• UI thread耗时texture方式最好,PowerImage略好于IFImage,FFI方式波动比较大。
• Raster thread耗时PowerImage好于IFImage。Origin原生方式好是因为对图片resize了,其他方式加载的是原图。
3. 更精简的代码
dart侧代码有较大幅度的减少,这归功于技术方案贴合flutter原生设计,我们与原生图片共用较多代码。
FFI方案补全了外接纹理的不足,遵循原生Image的设计规范,不仅让我们享受到ImageCache带来的统一管理,也带来了更精简的代码。
4. 单测
为了保证核心代码的稳定性,我们有着较为完善的单测,行覆盖率接近95%。
接下篇:https://developer.aliyun.com/article/1225984?groupCode=idlefish