【OpenHarmony】 鸿蒙图片加载库之ImageKnife

2 阅读9分钟

专门为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)

// 自定义实现图片获取方法,如自定义网络下载
@Concurrent
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> {
  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)

DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。

`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

7.支持option图片变换

ImageKnifeComponent({ ImageKnifeOption: 
{
   loadSrc: $r("app.media.rabbit"),
   border: {radius:50},
   transformation: new BlurTransformation(3)
  }
}).width(100).height(100)

多种组合变换用法

let transformations: collections.Array<PixelMapTransformation> = new collections.Array<PixelMapTransformation>();
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)

DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。

`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

13.rcp自定义网络请求

ImageKnifeComponent({
    loadSrc:"http//xx.xx",
    customGetImage:custom
})
// 自定义下载方法
@Concurrent
async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>): Promise<ArrayBuffer | undefined> {
  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组件

组件名称入参内容功能简介
ImageKnifeComponentImageKnifeOption图片显示组件
ImageKnifeAnimatorComponentImageKnifeOption、AnimatorOption动图控制组件

AnimatorOption参数列表

参数名称入参内容功能简介
stateAnimationStatus播放状态(可选)
iterationsnumber播放次数(可选)
reverseboolean播放顺序(可选)
onStart()=>void动画开始播放时触发(可选)
onFinish()=>void动画播放完成时或者停止播放时触发(可选)
onPause()=>void动画暂停播放时触发(可选)
onCancel()=>void动画返回最初状态时触发(可选)
onRepeat()=>void动画重复播放时触发(可选)

ImageKnifeOption参数列表

参数名称入参内容功能简介
loadSrcstring、PixelMap、Resource主图展示
placeholderSrcPixelMap、Resource占位图图展示(可选)
errorholderSrcPixelMap、Resource错误图展示(可选)
objectFitImageFit主图填充效果(可选)
placeholderObjectFitImageFit占位图填充效果(可选)
errorholderObjectFitImageFit错误图填充效果(可选)
writeCacheStrategyCacheStrategyType写入缓存策略(可选)
onlyRetrieveFromCacheboolean是否跳过网络和本地请求(可选)
customGetImagecustomGetImage?:(context: Context, src: string、PixelMap、Resource ,headers?: Record<string, Object>) => Promise<ArrayBuffer、undefined>自定义下载图片(可选)
Resource错误占位图数据源
borderBorderOptions边框圆角(可选)
prioritytaskpool.Priority加载优先级(可选)
contextcommon.UIAbilityContext上下文(可选)
progressListener(progress: number)=>void进度(可选)
signatureString自定义缓存关键字(可选)
headerOptionArray设置请求头(可选)
transformationPixelMapTransformation图片变换(可选)
drawingColorFilterColorFilter、drawing.ColorFilter颜色滤镜效果(可选)
onComplete(event:EventImage、undefined) => void图片成功回调事件(可选)
onLoadListeneronLoadStart?: (req?: ImageKnifeRequest) => void,onLoadSuccess?: (data: string | PixelMap | undefined, imageData: ImageKnifeData, req?: ImageKnifeRequest) => void,onLoadFailed?: (err: string, req?: ImageKnifeRequest) => void,onLoadCancel?: (res: string, req?: ImageKnifeRequest) => void监听图片加载成功与失败
downsampleOfDownsampleStrategy降采样(可选)
httpOptionHttpRequestOption网络请求配置(可选)

降采样类型

类型相关描述
NONE不进行降采样
AT_MOST请求尺寸大于实际尺寸不进行放大
FIT_CENTER_MEMORY两边自适应内存优先
FIT_CENTER_QUALITY两边自适应质量优先
CENTER_INSIDE_MEMORY宽高缩放比最大的比例,进行缩放适配内存优先
CENTER_INSIDE_QUALITY宽高缩放比最大的比例,进行缩放适配质量优先
AT_LEAST根据宽高的最小的比例,进行适配

ImageKnife接口

参数名称入参内容功能简介
initMemoryCachenewMemoryCache: IMemoryCache自定义内存缓存策略
initFileCachecontext: Context, size: number, memory: number初始化文件缓存数量和大小
reloadrequest: ImageKnifeRequest图片重新加载
preLoadloadSrc: string I ImageKnifeOption预加载返回图片请求request
cancelrequest: ImageKnifeRequest取消图片请求
preLoadCacheloadSrc: string I ImageKnifeOption预加载并返回文件缓存路径
getCacheImageloadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string)从内存或文件缓存中获取资源
addHeaderkey: string, value: Object全局添加http请求头
setHeaderOptionsArray全局设置http请求头
deleteHeaderkey: string全局删除http请求头
setCustomGetImagecustomGetImage?: (context: Context, src: string、PixelMap、Resource ,headers?: Record<string, Object>) => Promise<ArrayBuffer、undefined>全局设置自定义下载
setEngineKeyImplIEngineKey全局配置缓存key生成策略
putCacheImageurl: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string写入内存磁盘缓存
removeMemoryCacheurl: string、ImageKnifeOption清理指定内存缓存
removeFileCacheurl: string、ImageKnifeOption清理指定磁盘缓存
getCacheLimitSizecacheType?: CacheStrategy获取指定缓存的上限大小
getCurrentCacheNumcacheType?: CacheStrategy获取指定缓存的当前缓存图片个数
getCurrentCacheSizecacheType?: CacheStrategy获取指定缓存的当前大小
getCurrentCacheSizecacheType?: CacheStrategy获取指定缓存的当前大小

DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。

`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

回调接口说明

回调接口回调字段回调描述
onLoadStartreq: ImageKnifeRequestreq返回字段中包含了图片请求的信息,如图片的url及其组件的宽高,同时ImageKnifeRequest包含了ImageKnifeData,其中包含此次请求的开始及其检查内存缓存的时间点
onLoadSuccessdata: string、PixelMap、undefined, imageData: ImageKnifeData, req?: ImageKnifeRequestdata:加载成功的结果数据;imageData:图片的存入缓存中的信息 ,req:图片请求的信息,同时其中的ImageKnifeData,包含此次请求中图片的原始大小、图片的解码大小、格式、图片帧、请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束等时间点
onLoadFailederr: string, req?: ImageKnifeRequesterr:错误信息描述;req:图片请求的信息,同时其中的ImageKnifeData,包含此次请求错误信息(ErrorInfo,TimeInfo),ErrorInfo其中包含了,错误阶段、错误码及其网络请求的错误码;TimeInfo中包含请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束等时间点
onLoadCancelreason: string, req?: ImageKnifeRequestreason:取消回调原因;req:图片请求的信息,同时其中的ImageKnifeData,包含此次请求错误信息(ErrorInfo,TimeInfo),ErrorInfo其中包含了,错误阶段、错误码及其网络请求的错误码;TimeInfo中包含请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束及其请求取消等时间点

图形变换类型(需要为GPUImage添加依赖项)

类型相关描述
BlurTransformation模糊处理
BrightnessTransformation亮度滤波器
CropSquareTransformation正方形剪裁
CropTransformation自定义矩形剪裁
GrayScaleTransformation灰度级滤波器
InvertTransformation反转滤波器
KuwaharaTransformation桑原滤波器(使用GPUIImage)
MaskTransformation遮罩
PixelationTransformation像素化滤波器(使用GPUIImage)
SepiaTransformation乌墨色滤波器(使用GPUIImage)
SketchTransformation素描滤波器(使用GPUIImage)
SwirlTransformation扭曲滤波器(使用GPUIImage)
ToonTransformation动画滤波器(使用GPUIImage)
VignetterTransformation装饰滤波器(使用GPUIImage)

下载安装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)