• Lv0
    粉丝19

积分1115 / 贡献0

提问0答案被采纳62文章8

[经验分享] 图片三方库Imageknife3.x优化总结 原创 精华

马迪 显示全部楼层 发表于 2024-6-1 08:55:52
     总所周知,主流应用都有瀑布流下拉图片的页面,为了使页面更丝滑,通常需要对图片进行缓存。这种通用需求,对标竞品往往使用三方库来实现,比如安卓有Glide 、Picasso、ImageLoader。IOS有SDWebImage,Kingfisher,PINRemoteImage。当前鸿蒙应用开发,主要推荐使用@ohos/imageknife.
fakename.png


然而@ohos/imageknife 2.x版本主要网络下载图片和解析的逻辑虽然是使用异步promise的方式,原则上不阻塞主线程。但是,当在页面快速下滑时,由于有很多的图片同时请求和加载,还是会造成主线程整体执行时间过长,导致页面出现丢帧卡顿。

为了解决这个问题,我逐步开始分析@ohos/imageknife和glide的源码,决定对@ohos/imageknife做一次彻底的重构,也就是当前的3.x版本。根据目前从仿抖音应用测试快速下拉图片的页面测试数据来看,丢帧率已经从原来6%+,下降几乎为0%。于是乎,总结了下从3.x-->2.x主要的优化手段,相信这些方式不仅对三方库法,对应用开发也会有很大的借鉴意义。

1.把主要的逻辑移植到子线程里。
自API11以后,鸿蒙应用提供了TaskPool的能力(https://docs.openharmony.cn/page ... ool-introduction.md),因此我把图片加载的主要逻辑:网络下载+文件缓存读写+图片解码都通过TaskPool放到了子线程里执行,也就是说每个图片的请求基本上都是在子线程里执行,主线程仅保留内存缓存读写和最终的显示,从而降低主线程的时间消耗,大大降低丢帧率。

近期,Pixelmap,Resource等类型也将支持Sendable,届时子线程返回的Pixelmap对象可以改成Sendable对象,即支持引用传递,这样将会进一步减少对象序列化的时间和内存消耗,相信对性能会有更进一步的提升。

2.减少耗时API的使用
这里主要是说在2.x版本,使用了自定义组件的OnAreaChange消息时间获取了组件的宽高,然而这个API被确认为是一个耗时API,且在页面快速下滑时的调用频率非常之高。当前,在API12版本,替换成了OS提供的性能更好的onSizeChange事件,这个事件仅在组件宽度发生变化时才被调用,也就是快速下滑过程中是不被触发的。单就这个API得替换,也对整体丢帧率有了很大的改善。

3.减少不必要的请求,优先加载当前页面的图片
因为在快速下滑的场景,以及一些打开又马上关闭页面的场景,由于OS网络接口的并发限制,往往导致有很多图片在排队请求,导致给人的感觉是当前页面的图片要等前面加载完后才能显示。针对这个问题,首先建议应用开发者使用lazyforeach+reuse的方式实现下拉列表,尽量复用当前组件。其次在3.x的实现过程中,默认控制了下发taskpool的请求数(默认8),超过默认请求数的请求在内存中先排队,超过并发数的请求会做一个简单排队,而不是一股脑子全扔到taskpool里。等到排到时会优先判断当前组件是否已经被销毁了,如果被销毁了,则该请求直接放弃,不再下发taskpool请求了。这个简单实现,可以减少不少子线程的不必要请求,能大大提升图片的加载效率。

4.使用系统Image组件,替换2.x的Canvas组件。
没办法,目前大家都公认Image组件性能强于Canvas组件,且Image自带ObjectFit属性直接支持了各种常用的图片缩放模式。当然,也有应用提出一些缩放模式Image无法支持。对此,我的建议是反馈给OS,优先让系统组件支持。其次,也可以自己封装一个自定义组件,由于Image加载完成会有回调Pixelmap和宽高的接口,可以仍然自己使用Canvas来计算和绘制。

5.优化了Iamgeknife核心调度逻辑。
主要体现在并发排队,同时下发占位图和主图,网络请求等逻辑上。减少了之前代码部分不合理之处。以下是3.x的主要实现逻辑
fakename.png


3.x版本除了性能的提升外,还有如下能力和2.x版本同时做了增强:
1.支持自定义网络下载
2.支持多种图片变换,如高亮,模糊等
3.支持接口预加载图片,判断图片是否有缓存,以及删除图片缓存
4.支持接口回调启动加载,完成加载或加载失败
5.支持设置缓存策略
6.heric格式图片支持

未来ImageKnife即将实现以下特性:
1.对动图的控制
2.支持对图片的降采样设置,从而减少内存缓存的占用
3.对Sendable的支持
4.支持自定义格式图片解码(当前只能修改源码)

诚然,由于应用对性能苛刻的要求,目前ImageKnife只能随着OS一起优化,已经用到了不少API12和最新HarmonyOS的镜像的特性,放弃了对AP9,AI10的支持。 待后续OS API稳定后,我们也会思考下如何更好地兼容历史版本。


最后,希望ImageKnife能够被更多应用使用,如果大家有新的诉求,也欢迎大家多在论坛讨论,多提issue,多发PR~~~

附上传送门:https://gitee.com/openharmony-tpc/ImageKnife/tree/3.x/

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部