【OpenHarmony】 鸿蒙ImageKnife高效图像缓存库解析_鸿蒙 imageknife库
往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)
✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✏️ 市场巨变,移动开发行业即将迎来“第二春”?
✏️ 记录一场鸿蒙开发岗位面试经历~
✏️ 持续更新中……
专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。
简介
本项目参考开源库 Glide 进行OpenHarmony的自研版本:
- 支持自定义内存缓存策略,支持设置内存缓存的大小(默认LRU策略)。
- 支持磁盘二级缓存,对于下载图片会保存一份至磁盘当中。
- 支持自定义实现图片获取/网络下载
- 支持监听网络下载回调进度
- 继承Image的能力,支持option传入border,设置边框,圆角
- 继承Image的能力,支持option传入objectFit设置图片缩放,包括objectFit为auto时根据图片自适应高度
- 支持通过设置transform缩放图片
- 并发请求数量,支持请求排队队列的优先级
- 支持生命周期已销毁的图片,不再发起请求
- 自定义缓存key
- 自定义http网络请求头
- 支持writeCacheStrategy控制缓存的存入策略(只存入内存或文件缓存)
- 支持preLoadCache预加载图片
- 支持onlyRetrieveFromCache仅用缓存加载
- 支持使用一个或多个图片变换,如模糊,高亮等
待实现特性
- 内存降采样优化,节约内存的占用
- 支持自定义图片解码
注意:3.x版本相对2.x版本做了重大的重构,主要体现在:
- 使用Image组件代替Canvas组件渲染
- 重构Dispatch分发逻辑,支持控制并发请求数,支持请求排队队列的优先级
- 支持通过initMemoryCache自定义策略内存缓存策略和大小
- 支持option自定义实现图片获取/网络下载
因此API及能力上,目前有部分差异,主要体现在:
- 不支持drawLifeCycle接口,通过canvas自会图片
- mainScaleType,border等参数,新版本与系统Image保持一致
- gif/webp动图播放与控制(ImageAnimator实现)
- 抗锯齿相关参数
下载安装
ohpm install @ohos/imageknife// 如果需要用文件缓存,需要提前初始化文件缓存await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
使用说明
1.显示本地资源图片
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r(\"app.media.app_icon\"), placeholderSrc: $r(\"app.media.loading\"), errorholderSrc: $r(\"app.media.app_icon\"), objectFit: ImageFit.Auto }}).width(100).height(100)
2.显示本地context files下文件
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: this.localFile, placeholderSrc: $r(\"app.media.loading\"), errorholderSrc: $r(\"app.media.app_icon\"), objectFit: ImageFit.Auto }}).width(100).height(100)
3.显示网络图片
ImageKnifeComponent({ ImageKnifeOption: { loadSrc:\"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png\", placeholderSrc: $r(\"app.media.loading\"), errorholderSrc: $r(\"app.media.app_icon\"), objectFit: ImageFit.Auto }}).width(100).height(100)
4.自定义下载图片
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: \"https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg\", placeholderSrc: $r(\"app.media.loading\"), errorholderSrc: $r(\"app.media.app_icon\"), objectFit: ImageFit.Auto, customGetImage: custom }}).width(100).height(100)// 自定义实现图片获取方法,如自定义网络下载@Concurrentasync function custom(context: Context, src: string | PixelMap | Resource): Promise { console.info(\"ImageKnife:: custom download:\" + src) // 举例写死从本地文件读取,也可以自己请求网络图片 return context.resourceManager.getMediaContentSync($r(\"app.media.bb\").id).buffer as ArrayBuffer}
5.监听网络下载进度
ImageKnifeComponent({ ImageKnifeOption: { loadSrc:\"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png\", progressListener:(progress:number)=>{console.info(\"ImageKinfe:: call back progress = \" + progress)} }}).width(100).height(100)
6.支持option传入border,设置边框,圆角
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r(\"app.media.rabbit\"), border: {radius:50} }}).width(100).height(100)
7.支持option图片变换
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r(\"app.media.rabbit\"), border: {radius:50}, transformation: new BlurTransformation(3) }}).width(100).height(100)
多种组合变换用法
let transformations: collections.Array = new collections.Array();transformations.push(new BlurTransformation(5));transformations.push(new BrightnessTransformation(0.2));ImageKnifeComponent({ imageKnifeOption: { loadSrc: $r(\'app.media.pngSample\'), placeholderSrc: $r(\"app.media.loading\"), errorholderSrc: $r(\"app.media.app_icon\"), objectFit: ImageFit.Contain, border: { radius: { topLeft: 50, bottomRight: 50 } }, // 圆角设置 transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // 图形变换组}}).width(300) .height(300) .rotate({ angle: 90 }) // 旋转90度 .contrast(12) // 对比度滤波器
其它变换相关属性,可叠加实现组合变换效果
圆形裁剪变换示例
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r(\'app.media.pngSample\'), objectFit: ImageFit.Cover, border: { radius: 150 }}}).width(300) .height(300)
圆形裁剪带边框变换示例
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r(\'app.media.pngSample\'), objectFit: ImageFit.Cover, border: { radius: 150, color: Color.Red, width: 5 }}}).width(300) .height(300)
对比度滤波变换示例
ImageKnifeComponent({ imageKnifeOption: { loadSrc: $r(\'app.media.pngSample\') }}).width(300) .height(300) .contrast(12)
旋转变换示例
ImageKnifeComponent({ imageKnifeOption: { loadSrc: $r(\'app.media.pngSample\') }}).width(300) .height(300) .rotate({angle:90}) .backgroundColor(Color.Pink)
8.监听图片加载成功与失败
ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r(\"app.media.rabbit\"), onLoadListener:{ onLoadStart:()=>{ this.starTime = new Date().getTime() console.info(\"Load start: \"); }, onLoadFailed: (err) => { console.error(\"Load Failed Reason: \" + err + \" cost \" + (new Date().getTime() - this.starTime) + \" milliseconds\"); }, onLoadSuccess: (data, imageData) => { console.info(\"Load Successful: cost \" + (new Date().getTime() - this.starTime) + \" milliseconds\"); return data; }, onLoadCancel(err){ console.info(err) } } }}).width(100).height(100)
9.ImageKnifeComponent - syncLoad
设置是否同步加载图片,默认是异步加载。建议加载尺寸较小的Resource图片时将syncLoad设为true,因为耗时较短,在主线程上执行即可
ImageKnifeComponent({ imageKnifeOption:{ loadSrc:$r(\"app.media.pngSample\"), placeholderSrc:$r(\"app.media.loading\") },syncLoad:true })
10.ImageKnifeAnimatorComponent 示例
ImageKnifeAnimatorComponent({ imageKnifeOption: { loadSrc:\"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658\", placeholderSrc:$r(\'app.media.loading\'), errorholderSrc:$r(\'app.media.failed\') },animatorOption:this.animatorOption }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
11.加载图片回调信息数据 示例
ImageKnifeComponent({ ImageKnifeOption: = { loadSrc: $r(\'app.media.pngSample\'), objectFit: ImageFit.Contain, onLoadListener: { onLoadStart: (req) => { let startCallBackData = JSON.stringify(req?.imageKnifeData); }, onLoadFailed: (res, req) => { let failedBackData = res + \";\" + JSON.stringify(req?.imageKnifeData); }, onLoadSuccess: (data, imageData, req) => { let successBackData = JSON.stringify(req?.imageKnifeData); }, onLoadCancel: (res, req) => { let cancelBackData = res + \";\" + JSON.stringify(req?.imageKnifeData); } }, border: { radius: 50 }, onComplete: (event) => { if (event && event.loadingStatus == 0) { let render_success = JSON.stringify(Date.now()) } } }}).width(100).height(100)
12.图片降采样 示例
ImageKnifeComponent({ imageKnifeOption:{ loadSrc:$r(\"app.media.pngSample\"), placeholderSrc:$r(\'app.media.loading\'), errorholderSrc:$r(\'app.media.failed\'), downsampleOf: DownsampleStrategy.NONE } }).width(300).height(300)
13.rcp自定义网络请求
ImageKnifeComponent({ loadSrc:\"http//xx.xx\", customGetImage:custom})// 自定义下载方法@Concurrentasync function custom(context: Context, src: string | PixelMap | Resource,headers?: Record): Promise { return new Promise((resolve,reject)=>{ if (typeof src == \"string\") { let session = GetSession.session let req = new rcp.Request(src,\"GET\"); session.fetch(req).then((response)=>{ if(response.statusCode == 200) { let buffer = response.body resolve(buffer) } else { reject(\"rcp code:\"+response.statusCode) } }).catch((err:BusinessError)=>{ reject(\"error rcp src:\"+src+\",err:\"+JSON.stringify(err)) }) } })}
复用场景
在aboutToRecycle生命周期清空组件内容;通过watch监听触发图片的加载。
接口说明
ImageKnife组件
AnimatorOption参数列表
ImageKnifeOption参数列表
降采样类型
ImageKnife接口
回调接口说明
图形变换类型(需要为GPUImage添加依赖项)
下载安装GPUImage依赖
方法一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。
ohpm install @ohos/gpu_transform
方法二: 在工程的oh-package.json5中设置三方包依赖,配置示例如下:
\"dependencies\": { \"@ohos/gpu_transform\": \"^1.0.2\" }
约束与限制
在下述版本验证通过:
DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)