diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a8d36..5b5fbeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,49 @@ -## 3.1.1-rc.1 -- Photo reduction sampling -## 3.1.1-rc.0 -- 重构代码:抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中,降低函数复杂度 -## 3.1.0 +## 3.2.0-rc.2 +- Added callback information for image loading +- Added the interface for obtaining the upper limit and size of the current cache and the number of images corresponding to the current cache +- HTTPS custom certificate verification +- Add downsampling function to reduces memory cache consumption + +## 3.2.0-rc.1 +- Change the queue from Stack to Queue +- ShowPixelMap callback PixelMap assigns value to Image component to synchronize + +## 3.2.0-rc.0 +- Rollback the old version V1 decorator. V2 decorator will be provided in version 4.x +- The sub-thread network request is changed to asynchronous, thereby increasing the number of concurrent sub-thread network requests +- Set the concurrency through the setMaxRequests interface under the ImageKnife class +- aboutToRecycle life cycle clear image content +- Fixed bug for receive only the first onLoadStart for concurrent identical requests +- Modify the condition for determining whether to queue to be greater than or equal to maxRequests + +## 3.0.3 +- Released version 3.0.3 + +## 3.0.3-rc.0 +- Custom network method to add request header parameters + +## 3.0.2 +- Added new image reloading interface reload +- Added return request preload interface preload +- Added cancel request interface cancel + +## 3.0.2-rc.2 +- ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件 +- 文件缓存数量负数和超过INT最大值时默认为INT最大值 +- 修复宽高不等svg图片显示有毛边 - 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别 - 修复加载错误图后未去请求排队队列中的请求 - 子线程本地Resource参数类型转换成number - 修改使用hilog记录日志,默认打开debug级别的日志 -- file格式图片,fd同步close - 解码pixelMap默认不可编辑,图形变化可编辑 - 修改网络请求超时设置 +- 重构代码:抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中,降低函数复杂度 -## 3.1.0-rc.2 -- 修复宽高不等svg图片显示有毛边 +## 3.0.2-rc.1 +- release打包关闭混淆 -## 3.1.0-rc.1 -- ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件 -- 文件缓存数量负数和超过INT最大值时默认为INT最大值 - -## 3.1.0-rc.0 -- ComponentV2装饰器适配 -- imageKnifeOption={...}用法改为new ImageKnifeOption({...}) -- animatorOption={...}用法改为new AnimatorOption({...}) +## 3.0.2-rc.0 +- FileUtil.readFile接口和file格式图片同步关闭fd ## 3.0.1 - 修复animatorOption属性设置初始化值失效 diff --git a/README.md b/README.md index 23624dd..7d33085 100644 --- a/README.md +++ b/README.md @@ -56,12 +56,12 @@ await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024) ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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) ``` @@ -69,12 +69,12 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + ImageKnifeOption: { loadSrc: this.localFile, placeholderSrc: $r("app.media.loading"), errorholderSrc: $r("app.media.app_icon"), objectFit: ImageFit.Auto - }) + } }).width(100).height(100) ``` @@ -82,12 +82,12 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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) ``` @@ -95,13 +95,13 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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) // Custom implementation of the image acquisition method, such as custom network download。 @@ -117,33 +117,33 @@ async function custom(context: Context, src: string | PixelMap | Resource): Prom ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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. Setting Border Options ``` -ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), border: {radius:50} - }) + } }).width(100).height(100) ``` #### 7. Setting Image Transformation Options ``` -ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), border: {radius:50}, transformation: new BlurTransformation(3) - }) + } }).width(100).height(100) ``` Multiple combined transformation usages: @@ -153,14 +153,14 @@ let transformations: collections.Array = new collections transformations.push(new BlurTransformation(5)); transformations.push(new BrightnessTransformation(0.2)); ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + 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 } }, // Rounded corner settings transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // Graphic transformation group -}) +} }).width(300) .height(300) .rotate ({angle: 90}) // Rotate by 90 degrees. @@ -171,12 +171,12 @@ Other transformation-related properties can be stacked to achieve combined trans Example of circular cropping transformation: ``` -ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r('app.media.pngSample'), objectFit: ImageFit.Cover, border: { radius: 150 } -}) +} }).width(300) .height(300) ``` @@ -184,12 +184,12 @@ ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( Example of Circular cropping with border transformation: ``` -ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r('app.media.pngSample'), objectFit: ImageFit.Cover, border: { radius: 150, color: Color.Red, width: 5 } -}) +} }).width(300) .height(300) ``` @@ -198,9 +198,9 @@ Example of contrast filtering transformation: ``` ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: $r('app.media.pngSample') - }) + } }).width(300) .height(300) .contrast(12) @@ -210,9 +210,9 @@ Example of rotation transformation: ``` ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption:({ loadSrc: $r('app.media.pngSample') - }) + } }).width(300) .height(300) .rotate({angle:90}) @@ -222,7 +222,7 @@ ImageKnifeComponent({ #### 8. Listening for Image Loading Success and Failure ``` -ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), onLoadListener:{ @@ -241,40 +241,29 @@ ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( console.info(err) } } - }) + } }).width(100).height(100) ``` #### 9. Use of syncLoad **syncLoad** sets whether to load the image synchronously. By default, the image is loaded asynchronously. When loading a small image, you are advised to set **syncLoad** to **true** so that the image loading can be quickly completed on the main thread. ``` ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ + imageKnifeOption:{ loadSrc:$r("app.media.pngSample"), placeholderSrc:$r("app.media.loading") - }),syncLoad:true + },syncLoad:true }) ``` #### 10. Use of ImageKnifeAnimatorComponent ``` ImageKnifeAnimatorComponent({ - imageKnifeOption:new ImageKnifeOption({ + imageKnifeOption:{ loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }),animatorOption:this.animatorOption + },animatorOption:this.animatorOption }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) ``` -#### 11.图片降采样 示例 -``` -ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:$r("app.media.pngSample"), - placeholderSrc:$r('app.media.loading'), - errorholderSrc:$r('app.media.failed'), - downsampleOf: DownsampleStrategy.NONE - }),animatorOption:this.animatorOption - }).width(300).height(300) -``` #### Reuse Scenario Clear the component content in the **aboutToRecycle** lifecycle and trigger image loading through watch observeration. ## Available APIs @@ -319,17 +308,7 @@ Clear the component content in the **aboutToRecycle** lifecycle and trigger imag | drawingColorFilter | ColorFilter | Drawing color filter. Optional. | | onComplete | (event:EventImage \| undefined)=>void | Callback for image loading completion. Optional. | | onLoadListener | onLoadStart:()=>void,onLoadSuccess:(data:string\|Pixelmap)=>void | Callback for image loading events. Optional. | -| downsampleOf | DownsampleStrategy | 降采样(可选) | -### 降采样类型 -| 类型 | 相关描述 | -|---------------------|-------------------| -| NONE | 不进行降采样 | -| AT_MOST | 请求尺寸大于实际尺寸不进行放大 | -| FIT_CENTER_MEMORY | 两边自适应内存优先 | -| FIT_CENTER_QUALITY | 两边自适应质量优先 | -| CENTER_OUTSIDE_MEMORY | 宽高缩放比最大的比例,进行缩放适配内存优先 | -| CENTER_OUTSIDE_QUALITY | 宽高缩放比最大的比例,进行缩放适配质量优先 | -| AT_LEAST | 根据宽高的最小的比例,进行适配 | + ### ImageKnife | Parameter | Type | Description | @@ -380,7 +359,7 @@ Method 2: Set the third-party HAR as a dependency in the **oh-package.json5** fi This project has been verified in the following version: -DevEco Studio: 5.0 Canary3 (5.0.3.502), SDK: API 12 (5.0.0.31) +DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66) ## How to Contribute @@ -393,4 +372,4 @@ This project is licensed under [Apache License 2.0](https://gitee.com/openharmon ## Known Issues - The **ImageFit** attribute cannot be set for the **ImageKnifeAnimator** component. -- The **border** attribute of the **ImageKnifeAnimator** component cannot make the image rounded corners. +- The **border** attribute of the **ImageKnifeAnimator** component cannot make the image rounded corners. \ No newline at end of file diff --git a/README_zh.md b/README_zh.md index 97522da..9c8502a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -56,12 +56,12 @@ await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024) ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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) ``` @@ -69,12 +69,12 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + ImageKnifeOption: { loadSrc: this.localFile, placeholderSrc: $r("app.media.loading"), errorholderSrc: $r("app.media.app_icon"), objectFit: ImageFit.Auto - }) + } }).width(100).height(100) ``` @@ -82,12 +82,12 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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) ``` @@ -95,13 +95,13 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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) // 自定义实现图片获取方法,如自定义网络下载 @@ -117,33 +117,33 @@ async function custom(context: Context, src: string | PixelMap | Resource): Prom ``` ImageKnifeComponent({ - ImageKnifeOption: new ImageKnifeOption({ + 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: new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), border: {radius:50} - }) + } }).width(100).height(100) ``` #### 7.支持option图片变换 ``` -ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), border: {radius:50}, transformation: new BlurTransformation(3) - }) + } }).width(100).height(100) ``` 多种组合变换用法 @@ -153,14 +153,14 @@ let transformations: collections.Array = new collections transformations.push(new BlurTransformation(5)); transformations.push(new BrightnessTransformation(0.2)); ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + 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度 @@ -171,12 +171,12 @@ ImageKnifeComponent({ 圆形裁剪变换示例 ``` -ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r('app.media.pngSample'), objectFit: ImageFit.Cover, border: { radius: 150 } -}) +} }).width(300) .height(300) ``` @@ -184,12 +184,12 @@ ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( 圆形裁剪带边框变换示例 ``` -ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r('app.media.pngSample'), objectFit: ImageFit.Cover, border: { radius: 150, color: Color.Red, width: 5 } -}) +} }).width(300) .height(300) ``` @@ -198,9 +198,9 @@ ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ``` ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: $r('app.media.pngSample') - }) + } }).width(300) .height(300) .contrast(12) @@ -210,9 +210,9 @@ ImageKnifeComponent({ ``` ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: $r('app.media.pngSample') - }) + } }).width(300) .height(300) .rotate({angle:90}) @@ -222,7 +222,7 @@ ImageKnifeComponent({ #### 8.监听图片加载成功与失败 ``` -ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( +ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), onLoadListener:{ @@ -241,29 +241,97 @@ ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( console.info(err) } } - }) + } }).width(100).height(100) ``` #### 9.ImageKnifeComponent - syncLoad 设置是否同步加载图片,默认是异步加载。建议加载尺寸较小的Resource图片时将syncLoad设为true,因为耗时较短,在主线程上执行即可 ``` ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ + imageKnifeOption:{ loadSrc:$r("app.media.pngSample"), placeholderSrc:$r("app.media.loading") - }),syncLoad:true + },syncLoad:true }) ``` #### 10.ImageKnifeAnimatorComponent 示例 ``` ImageKnifeAnimatorComponent({ - imageKnifeOption:new ImageKnifeOption({ + imageKnifeOption: { loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }),animatorOption:this.animatorOption + },animatorOption:this.animatorOption }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) ``` + +#### 11.加载图片回调信息数据 示例 +``` +ImageKnifeComponent({ ImageKnifeOption: = new ImageKnifeOption({ + loadSrc: $r('app.media.pngSample'), + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (req) => { + let startCallBackData = JSON.stringify(req?.getImageKnifeData()); + }, + onLoadFailed: (res, req) => { + let failedBackData = res + ";" + JSON.stringify(req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + let successBackData = JSON.stringify(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + let cancelBackData = res + ";" + JSON.stringify(req?.getImageKnifeData()); + } + }, + 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 +}) +// 自定义下载方法 +@Concurrent +async 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监听触发图片的加载。 ## 接口说明 @@ -287,44 +355,72 @@ ImageKnifeAnimatorComponent({ ### ImageKnifeOption参数列表 -| 参数名称 | 入参内容 | 功能简介 | -|-----------------------|-------------------------------------------------------|-----------------| -| loadSrc | string、PixelMap、Resource | 主图展示 | -| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) | -| errorholderSrc | PixelMap、Resource | 错误图展示(可选) | -| objectFit | ImageFit | 主图填充效果(可选) | -| placeholderObjectFit | ImageFit | 占位图填充效果(可选) | -| errorholderObjectFit | ImageFit | 错误图填充效果(可选) | -| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) | -| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) | -| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 | -| border | BorderOptions | 边框圆角(可选) | -| priority | taskpool.Priority | 加载优先级(可选) | -| context | common.UIAbilityContext | 上下文(可选) | -| progressListener | (progress: number)=>void | 进度(可选) | -| signature | String | 自定义缓存关键字(可选) | -| headerOption | Array | 设置请求头(可选) | -| transformation | PixelMapTransformation | 图片变换(可选) | -| drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) | -| onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) | -| onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 | +| 参数名称 | 入参内容 | 功能简介 | +|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------| +| loadSrc | string、PixelMap、Resource | 主图展示 | +| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) | +| errorholderSrc | PixelMap、Resource | 错误图展示(可选) | +| objectFit | ImageFit | 主图填充效果(可选) | +| placeholderObjectFit | ImageFit | 占位图填充效果(可选) | +| errorholderObjectFit | ImageFit | 错误图填充效果(可选) | +| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) | +| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) | +| customGetImage | customGetImage?:(context: Context, src: string、PixelMap、Resource ,headers?: Record) => Promise | 自定义下载图片(可选) | | Resource | 错误占位图数据源 | +| border | BorderOptions | 边框圆角(可选) | +| priority | taskpool.Priority | 加载优先级(可选) | +| context | common.UIAbilityContext | 上下文(可选) | +| progressListener | (progress: number)=>void | 进度(可选) | +| signature | String | 自定义缓存关键字(可选) | +| headerOption | Array | 设置请求头(可选) | +| transformation | PixelMapTransformation | 图片变换(可选) | +| drawingColorFilter | ColorFilter、drawing.ColorFilter | 图片变换(可选) | +| onComplete | (event:EventImage、undefined) => void | 颜色滤镜效果(可选) | +| onLoadListener | onLoadStart?: (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 | 监听图片加载成功与失败 | +| downsampleOf | DownsampleStrategy | 降采样(可选) | + +### 降采样类型 +| 类型 | 相关描述 | +|---------------------|-------------------| +| NONE | 不进行降采样 | +| AT_MOST | 请求尺寸大于实际尺寸不进行放大 | +| FIT_CENTER_MEMORY | 两边自适应内存优先 | +| FIT_CENTER_QUALITY | 两边自适应质量优先 | +| CENTER_OUTSIDE_MEMORY | 宽高缩放比最大的比例,进行缩放适配内存优先 | +| CENTER_OUTSIDE_QUALITY | 宽高缩放比最大的比例,进行缩放适配质量优先 | +| AT_LEAST | 根据宽高的最小的比例,进行适配 | ### ImageKnife接口 -| 参数名称 | 入参内容 | 功能简介 | -|------------------|-------------------------------------------------------------------------------------------------------|---------------| -| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 | -| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | -| preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 | -| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 | -| addHeader | key: string, value: Object | 全局添加http请求头 | -| setHeaderOptions | Array | 全局设置http请求头 | -| deleteHeader | key: string | 全局删除http请求头 | -| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise | 全局设置自定义下载 | -| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | -| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | -| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 | -| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 | +| 参数名称 | 入参内容 | 功能简介 | +|-------------------|---------------------------------------------------------------------------------------------------------------------------------------|------------------| +| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 | +| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | +| reload | request: ImageKnifeRequest | 图片重新加载 | +| preLoad | loadSrc: string I ImageKnifeOption | 预加载返回图片请求request | +| cancel | request: ImageKnifeRequest | 取消图片请求 | +| preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 | +| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 | +| addHeader | key: string, value: Object | 全局添加http请求头 | +| setHeaderOptions | Array | 全局设置http请求头 | +| deleteHeader | key: string | 全局删除http请求头 | +| setCustomGetImage | customGetImage?: (context: Context, src: string、PixelMap、Resource ,headers?: Record) => Promise| 全局设置自定义下载 | +| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | +| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | +| removeMemoryCache | url: string、ImageKnifeOption | 清理指定内存缓存 | +| removeFileCache | url: string、ImageKnifeOption | 清理指定磁盘缓存 | +| getCacheLimitSize | cacheType?: CacheStrategy | 获取指定缓存的上限大小 | +| getCurrentCacheNum | cacheType?: CacheStrategy | 获取指定缓存的当前缓存图片个数 | +| getCurrentCacheSize | cacheType?: CacheStrategy | 获取指定缓存的当前大小 | +| getCurrentCacheSize | cacheType?: CacheStrategy | 获取指定缓存的当前大小 | + +### 回调接口说明 +| 回调接口 | 回调字段 | 回调描述 | +|----------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| onLoadStart | req: ImageKnifeRequest | req返回字段中包含了图片请求的信息,如图片的url及其组件的宽高,同时ImageKnifeRequest包含了ImageKnifeData,其中包含此次请求的开始及其检查内存缓存的时间点 | +| onLoadSuccess | data: string、PixelMap、undefined, imageData: ImageKnifeData, req?: ImageKnifeRequest | data:加载成功的结果数据;imageData:图片的存入缓存中的信息 ,req:图片请求的信息,同时其中的ImageKnifeData,包含此次请求中图片的原始大小、图片的解码大小、格式、图片帧、请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束等时间点 | +| onLoadFailed | err: string, req?: ImageKnifeRequest | err:错误信息描述;req:图片请求的信息,同时其中的ImageKnifeData,包含此次请求错误信息(ErrorInfo,TimeInfo),ErrorInfo其中包含了,错误阶段、错误码及其网络请求的错误码;TimeInfo中包含请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束等时间点 | +| onLoadCancel | reason: string, req?: ImageKnifeRequest | reason:取消回调原因;req:图片请求的信息,同时其中的ImageKnifeData,包含此次请求错误信息(ErrorInfo,TimeInfo),ErrorInfo其中包含了,错误阶段、错误码及其网络请求的错误码;TimeInfo中包含请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束及其请求取消等时间点 | + ### 图形变换类型(需要为GPUImage添加依赖项) | 类型 | 相关描述 | @@ -358,7 +454,7 @@ ImageKnifeAnimatorComponent({ ## 约束与限制 在下述版本验证通过: -DevEco Studio 5.0 Canary3(5.0.3.502)--SDK:API12 (5.0.0.31) +DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66) ## 贡献代码 diff --git a/entry/src/main/ets/common/CustomEngineKeyImpl.ets b/entry/src/main/ets/common/CustomEngineKeyImpl.ets index 63437c3..acd2f4a 100644 --- a/entry/src/main/ets/common/CustomEngineKeyImpl.ets +++ b/entry/src/main/ets/common/CustomEngineKeyImpl.ets @@ -12,8 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { DownsampleStrategy } from '@ohos/imageknife'; -import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource} from '@ohos/libraryimageknife'; +import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource, + DownsampleStrategy} from '@ohos/libraryimageknife'; //全局自定义key demo @Sendable @@ -36,8 +36,8 @@ export class CustomEngineKeyImpl implements IEngineKey { if (imageKnifeOption.transformation) { key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";" } - if ((imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE && imageKnifeOption.downsampleOf !== undefined)) { - key += "downsampleOf" + imageKnifeOption.downsampleOf +"width="+width+"height="+ height + if ((imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE && imageKnifeOption.downsampleOf !== undefined)) { + key += "downsampleOf" + imageKnifeOption.downsampleOf + "width=" + width + "height=" + height } } return key diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index e19ffa7..2a48190 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -17,7 +17,7 @@ import hilog from '@ohos.hilog'; import UIAbility from '@ohos.app.ability.UIAbility'; import Want from '@ohos.app.ability.Want'; import window from '@ohos.window'; -import { ImageKnife, InitImageKnife, LogUtil } from '@ohos/libraryimageknife'; +import { ImageKnife, InitImageKnife } from '@ohos/libraryimageknife'; import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl'; import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; import { BusinessError } from '@ohos.base' diff --git a/entry/src/main/ets/pages/DownSamplePage.ets b/entry/src/main/ets/pages/DownSamplePage.ets index 8a59b89..73ebe5b 100644 --- a/entry/src/main/ets/pages/DownSamplePage.ets +++ b/entry/src/main/ets/pages/DownSamplePage.ets @@ -20,100 +20,100 @@ import { Downsampler } from '@ohos/imageknife/src/main/ets/downsampling/Downsamp import { FileTypeUtil } from '@ohos/imageknife/src/main/ets/utils/FileTypeUtil'; @Entry -@ComponentV2 +@Component struct DownSamplePage { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain - }) + } isBrightness: boolean = false - @Local beforeSampling: number = 0 - @Local afterSampling: number = 0 - @Local SamplingList: SamplingType[] = [ + @State beforeSampling: number = 0 + @State afterSampling: number = 0 + @State SamplingList: SamplingType[] = [ - new SamplingType(7, "AT_LEAST"), - new SamplingType(1, "AT_MOST"), + new SamplingType(7, 'AT_LEAST'), + new SamplingType(1, 'AT_MOST'), - new SamplingType(2, "FIT_CENTER_MEMORY"), - new SamplingType(4, "FIT_CENTER_QUALITY"), - new SamplingType(5, "CENTER_OUTSIDE_MEMORY"), - new SamplingType(6, "CENTER_OUTSIDE_QUALITY"), - new SamplingType(0, "NONE"), + new SamplingType(2, 'FIT_CENTER_MEMORY'), + new SamplingType(4, 'FIT_CENTER_QUALITY'), + new SamplingType(5, 'CENTER_OUTSIDE_MEMORY'), + new SamplingType(6, 'CENTER_OUTSIDE_QUALITY'), + new SamplingType(0, 'NONE'), ] - @Local checked: boolean = false + @State checked: boolean = false updateImageKnifeOption(value: string) { if (value === 'NONE') { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.NONE - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } else if (value === 'AT_MOST') { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.AT_MOST - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } else if (value === 'FIT_CENTER_MEMORY') { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.FIT_CENTER_MEMORY - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } else if (value === 'FIT_CENTER_QUALITY') { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.FIT_CENTER_QUALITY - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } else if (value === 'CENTER_OUTSIDE_MEMORY') { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.CENTER_OUTSIDE_MEMORY - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } else if (value === 'CENTER_OUTSIDE_QUALITY') { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.CENTER_OUTSIDE_QUALITY - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } else { - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, downsampleOf: DownsampleStrategy.AT_LEAST - }) + } this.originalPixMap($r('app.media.pngSample')) this.afterSamplingFunc($r('app.media.pngSample')) } @@ -130,7 +130,7 @@ struct DownSamplePage { } let imageInfo = await imageSource.getImageInfo() - if (this.imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE){ + if (this.imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE && this.imageKnifeOption.downsampleOf != undefined ) { let reqSize = new Downsampler().calculateScaling(typeValue, imageInfo.size.width, imageInfo.size.height, 300, 300, this.imageKnifeOption.downsampleOf) @@ -147,7 +147,7 @@ struct DownSamplePage { imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => { this.afterSampling = pixelMap.getPixelBytesNumber() }).catch((err: BusinessError) => { - console.error("Failed to create PixelMap") + console.error('Failed to create PixelMap') }); } @@ -162,7 +162,7 @@ struct DownSamplePage { imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => { this.beforeSampling = pixelMap.getPixelBytesNumber() }).catch((err: BusinessError) => { - console.error("Failed to create PixelMap") + console.error('Failed to create PixelMap') }); } getResourceString(res:Resource){ diff --git a/entry/src/main/ets/pages/ImageAnimatorPage.ets b/entry/src/main/ets/pages/ImageAnimatorPage.ets index 5837f7f..8c923a5 100644 --- a/entry/src/main/ets/pages/ImageAnimatorPage.ets +++ b/entry/src/main/ets/pages/ImageAnimatorPage.ets @@ -12,37 +12,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { AnimatorOption, ImageKnifeAnimatorComponent,ImageKnifeOption } from "@ohos/libraryimageknife" +import { AnimatorOption, ImageKnifeAnimatorComponent } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct ImageAnimatorPage { - @Local animatorOption: AnimatorOption = new AnimatorOption({ + @State animatorOption: AnimatorOption = { state: AnimationStatus.Running, - iterations: -1, + iterations: 1, onFinish:()=>{ - console.log("ImageKnifeAnimatorComponent animatorOption onFinish") + console.log('ImageKnifeAnimatorComponent animatorOption onFinish') }, onStart:()=>{ - console.log("ImageKnifeAnimatorComponent animatorOption onStart") + console.log('ImageKnifeAnimatorComponent animatorOption onStart') }, onPause:()=>{ - console.log("ImageKnifeAnimatorComponent animatorOption onPause") + console.log('ImageKnifeAnimatorComponent animatorOption onPause') }, onCancel:()=>{ - console.log("ImageKnifeAnimatorComponent animatorOption onCancel") + console.log('ImageKnifeAnimatorComponent animatorOption onCancel') }, onRepeat:()=>{ - console.log("ImageKnifeAnimatorComponent animatorOption onRepeat") + console.log('ImageKnifeAnimatorComponent animatorOption onRepeat') } - }) - @Local animatorOption1: AnimatorOption = new AnimatorOption({ + } + @State animatorOption1: AnimatorOption = { state: AnimationStatus.Initial - }) - @Local animatorOption2: AnimatorOption = new AnimatorOption({ + } + @State animatorOption2: AnimatorOption = { state: AnimationStatus.Initial, reverse: true - }) + } build() { Column(){ Flex(){ @@ -66,28 +66,28 @@ struct ImageAnimatorPage { }) } ImageKnifeAnimatorComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + imageKnifeOption:{ + loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }),animatorOption:this.animatorOption - }).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) + },animatorOption:this.animatorOption + }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) Text($r('app.string.Display_the_first_frame')).fontSize(20) ImageKnifeAnimatorComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + imageKnifeOption:{ + loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }),animatorOption:this.animatorOption1 + },animatorOption:this.animatorOption1 }).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) Text($r('app.string.Display_the_last_frame')).fontSize(20) ImageKnifeAnimatorComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + imageKnifeOption:{ + loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }),animatorOption:this.animatorOption2 + },animatorOption:this.animatorOption2 }).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) - }.width("100%").height("100%") + }.width('100%').height('100%') } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/ImageKnifeReload.ets b/entry/src/main/ets/pages/ImageKnifeReload.ets new file mode 100644 index 0000000..e8aefa7 --- /dev/null +++ b/entry/src/main/ets/pages/ImageKnifeReload.ets @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { connection } from '@kit.NetworkKit' +import { List } from '@kit.ArkTS' +import { ImageKnifeRequest,ImageKnife,ImageKnifeComponent } from '@ohos/libraryimageknife' + +@Entry +@Component +struct ImageKnifeReload { + aboutToAppear(): void { + NetWatchState.init() + } + build() { + Column() { + ImageKnifeComponent({ + imageKnifeOption:{ + loadSrc:'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', + placeholderSrc:$r('app.media.loading'), + errorholderSrc:$r('app.media.failed'), + onLoadListener:{ + onLoadFailed(err,request){ + NetWatchState.requestList.add(request) + } + } + } + }).width(200).height(200) + ImageKnifeComponent({ + imageKnifeOption:{ + loadSrc:'https://img-blog.csdn.net/20140514114029140', + placeholderSrc:$r('app.media.loading'), + errorholderSrc:$r('app.media.failed'), + onLoadListener:{ + onLoadFailed(err,request){ + NetWatchState.requestList.add(request) + } + } + } + }).width(200).height(200).margin({top:10}) + }.width('100%') + .height('100%') + } +} + +class NetWatchState { + public static netConnection: connection.NetConnection | undefined = undefined + public static requestList: List = new List() + + static init() { + NetWatchState.netConnection = connection.createNetConnection() + // 注册订阅事件 + NetWatchState.netConnection.register(()=>{ + }) + // 订阅网络能力变化事件。调用register后,才能接收到此事件通知 + NetWatchState.netConnection.on('netCapabilitiesChange',(data:connection.NetCapabilityInfo)=>{ + if(NetWatchState.requestList.length > 0 && data.netHandle.netId >= 100) { + NetWatchState.requestList.forEach((request)=>{ + ImageKnife.getInstance().reload(request) + NetWatchState.requestList.remove(request) + }) + } + }) + } + + static cancel(){ + if(NetWatchState.netConnection != undefined) { + // 取消订阅 + NetWatchState.netConnection.unregister(()=>{}) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/ImageTransformation.ets b/entry/src/main/ets/pages/ImageTransformation.ets index 5a88f34..d085527 100644 --- a/entry/src/main/ets/pages/ImageTransformation.ets +++ b/entry/src/main/ets/pages/ImageTransformation.ets @@ -35,17 +35,17 @@ import { import { collections } from '@kit.ArkTS' @Entry -@ComponentV2 +@Component struct ImageTransformation { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain - }) - @Local isRound: boolean = false; - @Local isContrast: boolean = false; - @Local isRotate: boolean = false; + } + @State isRound: boolean = false; + @State isContrast: boolean = false; + @State isRotate: boolean = false; isBlur: boolean = false isBrightness: boolean = false isGrayScale: boolean = false; @@ -412,14 +412,14 @@ struct ImageTransformation { if (this.isMask) { transformations.push(new MaskTransformation($r('app.media.mask_starfish'))); } - this.imageKnifeOption = new ImageKnifeOption({ + this.imageKnifeOption = { loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, border: { radius: this.isRound ? { topLeft: 50, bottomRight: 50 } : 0 }, transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined - }) + } if (this.isCropCircle) { this.imageKnifeOption.objectFit = ImageFit.Cover; this.imageKnifeOption.border = { radius: 150 }; diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index def6a65..2e68f9b 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -15,153 +15,165 @@ import router from '@system.router'; @Entry -@ComponentV2 +@Component struct Index { - getResourceString(res: Resource) { + + getResourceString(res:Resource){ return getContext().resourceManager.getStringSync(res.id) } + aboutToAppear(): void { } build() { - Scroll() { + Scroll(){ Column() { - Button($r('app.string.Test_ImageAnimator')).onClick(() => { + Button($r('app.string.Test_ImageAnimator')).onClick(()=>{ router.push({ uri: 'pages/ImageAnimatorPage', }); }) - Button($r('app.string.Test_multiple_images')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Network_reload')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/ImageKnifeReload', + }); + }) + Button($r('app.string.preloading_prefetch')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/PrefetchAndCacheCount', + }); + }) + Button($r('app.string.request_concurrency')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/SetMaxRequestPage', + }); + }) + Button($r('app.string.Test_multiple_images')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/TestCommonImage', }); }) - Button(this.getResourceString($r('app.string.Multiple_images')) + " + reuse + LazyForeach") - .margin({ top: 10 }) - .onClick(() => { - router.push({ - uri: 'pages/UserPage', + Button($r('app.string.Test_Task_error')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestTaskResourcePage', + }); + }) + Button($r('app.string.Test_HSP')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestHspPreLoadImage', - }); - }) - Button($r('app.string.Test_SingleImage')).margin({ top: 10 }).onClick(() => { + }); + }) + Button($r('app.string.Test_SingleImage')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/SingleImage', }); }) + Button($r('app.string.Test_custom_download')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestSetCustomImagePage', + + }); + }) + Button(this.getResourceString($r('app.string.Multiple_images')) + ' + reuse + LazyForeach').margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/UserPage', + + }); + }) Button($r('app.string.Image_Downsampling_Functionality')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/DownSamplePage', }); }) - Button($r('app.string.Display_long_image')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Display_long_image')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/LongImagePage', }); }) - Button($r('app.string.Image_Transformation')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Image_scaling')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TransformPage', + + }); + }) + Button(this.getResourceString($r('app.string.Message_list')) + ' + List').margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestImageFlash', + + }); + }) + Button($r('app.string.Custom_cache_key')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/SignatureTestPage', + + }); + }) + Button($r('app.string.Preloading_images_to_cache')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestPrefetchToFileCache', + + }); + }) + Button($r('app.string.Retrieve_image_display_from_cache')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestIsUrlExist', + + }); + }) + Button($r('app.string.Test_single_request_header')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestHeader', + + }); + }) + Button($r('app.string.Test_write_cache_strategy')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestWriteCacheStage', + + }); + }) + Button($r('app.string.Image_Transformation')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/ImageTransformation', }); }) - Button($r('app.string.Test_media_URL')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/dataShareUriLoadPage', - }); - }) - Button($r('app.string.Different_ObjectFit')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Different_ObjectFit')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/ObjectFitPage', }); }) - Button($r('app.string.Custom_cache_key')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/SignatureTestPage', - }); - }) - Button($r('app.string.Test_image_loading_success_or_failure_events')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Test_image_loading_success_or_failure_events')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/LoadStatePage', }) }) - Button($r('app.string.Image_scaling')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TransformPage', - }); - }) - - Button($r('app.string.Test_HSP')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestHspPreLoadImage', - - }); - }) - - Button($r('app.string.Test_custom_download')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestSetCustomImagePage', - - }); - }) - - Button(this.getResourceString($r('app.string.Message_list')) + " + List").margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestImageFlash', - - }); - }) - - Button($r('app.string.Preloading_images_to_cache')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestPrefetchToFileCache', - - }); - }) - Button($r('app.string.Retrieve_image_display_from_cache')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestIsUrlExist', - - }); - }) - Button($r('app.string.Test_single_request_header')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestHeader', - - }); - }) - Button($r('app.string.Test_write_cache_strategy')).margin({ top: 10 }).onClick(() => { - router.push({ - uri: 'pages/TestWriteCacheStage', - - }); - }) - - - Button($r('app.string.Test_removing_image_cache_interface')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Test_removing_image_cache_interface')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/TestRemoveCache', }); }) - Button($r('app.string.Test_error_image_display')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Test_error_image_display')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/TestErrorHolderPage', }); }) - Button($r('app.string.Test_Task_error')).margin({ top: 10 }).onClick(() => { + Button($r('app.string.Test_media_URL')).margin({top:10}).onClick(()=>{ router.push({ - uri: 'pages/TestTaskResourcePage', + uri: 'pages/dataShareUriLoadPage', + }); }) Button($r('app.string.test_cache_btn')).margin({ top: 10 }).onClick(() => { @@ -179,8 +191,14 @@ struct Index { uri: 'pages/TestLoadCancelListenerPage', }); }) + Button($r('app.string.test_callback')).margin({ top: 10 }).onClick(() => { + router.push({ + uri: 'pages/TestImageKnifeCallbackPage', + + }); + }) } - }.width('100%') + } .width('100%') .height('100%') } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/LazyForEachCache.ets b/entry/src/main/ets/pages/LazyForEachCache.ets new file mode 100644 index 0000000..940592c --- /dev/null +++ b/entry/src/main/ets/pages/LazyForEachCache.ets @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { InfoItem } from './model/DataSourcePrefetching'; +import { PageViewModel } from './model/PageViewModel'; +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +export struct LazyForEachCache { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + aboutToAppear(): void { + this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems()) + } + build() { + Column() { + List({ space: 16 }) { + LazyForEach(this.hotCommendList, (item: InfoItem,index) => { + ListItem() { + Column({ space: 12 }) { + ImageKnifeComponent({ + imageKnifeOption:{ + loadSrc: item.albumUrl, + placeholderSrc:$r('app.media.loading') + } + }).width(100).height(100) + Text(`${index}`) + }.border({ width: 5 , color: '#000000'}) + } + }) + } + .cachedCount(5) + .width('100%') + .height('100%') + .margin({ left: 10, right: 10 }) + .layoutWeight(1) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/LazyForEachCount.ets b/entry/src/main/ets/pages/LazyForEachCount.ets new file mode 100644 index 0000000..7cfab01 --- /dev/null +++ b/entry/src/main/ets/pages/LazyForEachCount.ets @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { InfoItem } from './model/DataSourcePrefetching'; +import { PageViewModel } from './model/PageViewModel'; +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +export struct LazyForEachCount { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + aboutToAppear(): void { + this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems()) + } + build() { + Column() { + List({ space: 16 }) { + LazyForEach(this.hotCommendList, (item: InfoItem,index) => { + ListItem() { + Column({ space: 12 }) { + ImageKnifeComponent({ + imageKnifeOption:{ + loadSrc: item.albumUrl, + placeholderSrc:$r('app.media.loading') + } + }).width(100).height(100) + Text(`${index}`) + }.border({ width: 5 , color: '#000000'}) + } + }) + } + .cachedCount(30) + .width('100%') + .height('100%') + .margin({ left: 10, right: 10 }) + .layoutWeight(1) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/ListPage.ets b/entry/src/main/ets/pages/ListPage.ets index 1c6d614..c604d97 100644 --- a/entry/src/main/ets/pages/ListPage.ets +++ b/entry/src/main/ets/pages/ListPage.ets @@ -15,11 +15,11 @@ import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; @Entry -@ComponentV2 +@Component struct ListPage { private data: string[] = [] - @Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ loadSrc: $r('app.media.startIcon')}) + @State ImageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon')} aboutToAppear(): void { diff --git a/entry/src/main/ets/pages/LoadStatePage.ets b/entry/src/main/ets/pages/LoadStatePage.ets index 876a74e..a365e06 100644 --- a/entry/src/main/ets/pages/LoadStatePage.ets +++ b/entry/src/main/ets/pages/LoadStatePage.ets @@ -12,37 +12,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife" +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' import matrix4 from '@ohos.matrix4' @Entry -@ComponentV2 +@Component struct LoadStatePage { starTime:number = new Date().getTime() - @Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ - loadSrc: $r("app.media.rabbit"), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + @State ImageKnifeOption: ImageKnifeOption = { + loadSrc: $r('app.media.rabbit'), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, onLoadListener: { onLoadFailed: (err) => { - console.error("Load Failed Reason: " + err); + console.error('Load Failed Reason: ' + err); }, onLoadSuccess: (data) => { return data; }, }, border: { radius: 50 } - }) - @Local imageKnifeOption1: ImageKnifeOption = new ImageKnifeOption({ + } + @State imageKnifeOption1: ImageKnifeOption = { loadSrc: $r('app.media.startIcon') - }) - @Local message: string = "" - @Local currentWidth: number = 200 - @Local currentHeight: number = 200 - @Local typeValue: string = "" + } + @State message: string = '' + @State currentWidth: number = 200 + @State currentHeight: number = 200 + @State typeValue: string = '' build() { Column() { Text($r('app.string.TIPS')) @@ -50,21 +50,21 @@ struct LoadStatePage { Row() { Button($r('app.string.Test_failure_success')) .onClick(() => { - this.ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + this.ImageKnifeOption = { + loadSrc: 'https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png', + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, onLoadListener: { onLoadStart:()=>{ this.starTime = new Date().getTime() - console.info("Load start: "); + console.info('Load start: '); }, onLoadFailed: (err) => { - console.error("Load Failed Reason: " + err + " cost " + (new Date().getTime() - this.starTime) + " milliseconds"); + 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"); + console.info('Load Successful: cost ' + (new Date().getTime() - this.starTime) + ' milliseconds'); this.currentWidth = imageData.imageWidth! this.currentHeight = imageData.imageHeight! this.typeValue = imageData.type! @@ -73,9 +73,9 @@ struct LoadStatePage { }, border: { radius: 50 }, onComplete:(event)=>{ - console.error("Load onComplete width:"+event?.width , " height:"+event?.height , " componentWidth:"+event?.componentWidth," componentHeight:" + event?.componentHeight); + console.error('Load onComplete width:'+event?.width , ' height:'+event?.height , ' componentWidth:'+event?.componentWidth,' componentHeight:' + event?.componentHeight); } - }) + } }) } .margin({ top: 20 }) @@ -85,17 +85,17 @@ struct LoadStatePage { ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth) .margin({ top: 20 }) Button($r('app.string.Custom_download_failed')).onClick(()=>{ - this.imageKnifeOption1 = new ImageKnifeOption({ - loadSrc: "abc", + this.imageKnifeOption1 = { + loadSrc: 'abc', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed'), customGetImage:custom, onLoadListener: { onLoadFailed:(err)=>{ - this.message = "err:" + err + this.message = 'err:' + err } } - }) + } }).margin({ top: 20 }) Text(this.message).fontSize(20).margin({ top: 20 }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).height(this.currentHeight).width(this.currentWidth) @@ -109,8 +109,8 @@ struct LoadStatePage { } // 自定义下载方法 @Concurrent -async function custom(context: Context, src: string | PixelMap | Resource): Promise { - console.info("ImageKnife:: custom download:" + src) +async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record): Promise { + console.info('ImageKnife:: custom download:' + src) // 举例写死从本地文件读取,也可以自己请求网络图片 return undefined } \ No newline at end of file diff --git a/entry/src/main/ets/pages/LongImagePage.ets b/entry/src/main/ets/pages/LongImagePage.ets index 0d09a96..34d38fa 100644 --- a/entry/src/main/ets/pages/LongImagePage.ets +++ b/entry/src/main/ets/pages/LongImagePage.ets @@ -12,26 +12,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' +import { ImageKnifeComponent } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct LongImagePage { build() { Scroll() { - // Image("https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg").objectFit(ImageFit.Auto).height(300) + // Image('https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg').objectFit(ImageFit.Auto).height(300) - // Image($r("app.media.aaa")).objectFit(ImageFit.Auto).width(200) + // Image($r('app.media.aaa')).objectFit(ImageFit.Auto).width(200) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc:"https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg", - //src:$r("app.media.aaa"), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + imageKnifeOption: { + loadSrc:'https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg', + //src:$r('app.media.aaa'), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Auto - }) + } }) } .height('100%') .width('100%') diff --git a/entry/src/main/ets/pages/MaxRequest1.ets b/entry/src/main/ets/pages/MaxRequest1.ets new file mode 100644 index 0000000..e4bd67f --- /dev/null +++ b/entry/src/main/ets/pages/MaxRequest1.ets @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ImageKnifeComponent,ImageKnife } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +struct MaxRequest1 { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + private data: Array = [] + aboutToAppear(): void { + ImageKnife.getInstance().setMaxRequests(8) + for (let index = 0; index < 200; index++) { + this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`) + } + this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data) + } + build() { + Column() { + WaterFlow() { + LazyForEach(this.hotCommendList,(item: string)=>{ + FlowItem() { + Column(){ + ImageKnifeComponent({ + imageKnifeOption: { + loadSrc: item, + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), + } + }).width('50%').height(160) + } + }.height(200) + .backgroundColor('#95efd2') + },(item: string) => item) + }.columnsTemplate('1fr 1fr') + .cachedCount(8) + .columnsGap(10) + .rowsGap(5) + .backgroundColor(0xFAEEE0) + .width('100%').height('100%') + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/MaxRequest2.ets b/entry/src/main/ets/pages/MaxRequest2.ets new file mode 100644 index 0000000..22334ad --- /dev/null +++ b/entry/src/main/ets/pages/MaxRequest2.ets @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ImageKnifeComponent,ImageKnife } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +struct MaxRequest2 { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + private data: Array = [] + aboutToAppear(): void { + ImageKnife.getInstance().setMaxRequests(20) + for (let index = 200; index < 400; index++) { + this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`) + } + this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data) + } + build() { + Column() { + WaterFlow() { + LazyForEach(this.hotCommendList,(item: string)=>{ + FlowItem() { + Column(){ + ImageKnifeComponent({ + imageKnifeOption: { + loadSrc: item, + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), + } + }).width('50%').height(160) + } + }.height(200) + .backgroundColor('#95efd2') + },(item: string) => item) + }.columnsTemplate('1fr 1fr') + .cachedCount(20) + .columnsGap(10) + .rowsGap(5) + .backgroundColor(0xFAEEE0) + .width('100%').height('100%') + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/MaxRequest3.ets b/entry/src/main/ets/pages/MaxRequest3.ets new file mode 100644 index 0000000..38425ee --- /dev/null +++ b/entry/src/main/ets/pages/MaxRequest3.ets @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ImageKnifeComponent,ImageKnife } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +struct MaxRequest3 { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + private data: Array = [] + aboutToAppear(): void { + ImageKnife.getInstance().setMaxRequests(32) + for (let index = 400; index < 600; index++) { + this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`) + } + this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data) + } + build() { + Column() { + WaterFlow() { + LazyForEach(this.hotCommendList,(item: string)=>{ + FlowItem() { + Column(){ + ImageKnifeComponent({ + imageKnifeOption: { + loadSrc: item, + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), + } + }).width('50%').height(160) + } + }.height(200) + .backgroundColor('#95efd2') + },(item: string) => item) + }.columnsTemplate('1fr 1fr') + .cachedCount(40) + .columnsGap(10) + .rowsGap(5) + .backgroundColor(0xFAEEE0) + .width('100%').height('100%') + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/ObjectFitPage.ets b/entry/src/main/ets/pages/ObjectFitPage.ets index 58ca101..e47a860 100644 --- a/entry/src/main/ets/pages/ObjectFitPage.ets +++ b/entry/src/main/ets/pages/ObjectFitPage.ets @@ -15,49 +15,49 @@ import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct ObjectFitPage { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ - loadSrc: $r("app.media.app_icon"), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + @State imageKnifeOption: ImageKnifeOption = { + loadSrc: $r('app.media.app_icon'), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Fill - }) + } build() { Column() { Button($r('app.string.Main_image_Fill')).onClick(()=>{ - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: $r("app.media.app_icon"), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + this.imageKnifeOption = { + loadSrc: $r('app.media.app_icon'), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Fill - }) + } }) Button($r('app.string.Maintain_proportion_filling')).margin({top:10}).onClick(async () => { ImageKnife.getInstance().removeAllMemoryCache() await ImageKnife.getInstance().removeAllFileCache() - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: "https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg", - placeholderSrc: $r("app.media.app_icon"), - errorholderSrc: $r("app.media.app_icon"), + this.imageKnifeOption = { + loadSrc: 'https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg', + placeholderSrc: $r('app.media.app_icon'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Fill, placeholderObjectFit: ImageFit.Contain - }) + } }) Button($r('app.string.Error_graph_None')).margin({top:10}).onClick(() => { - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: "http://xxxxx", - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + this.imageKnifeOption = { + loadSrc: 'http://xxxxx', + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Fill, errorholderObjectFit: ImageFit.None - }) + } }) ImageKnifeComponent({ diff --git a/entry/src/main/ets/pages/PrefetchAndCacheCount.ets b/entry/src/main/ets/pages/PrefetchAndCacheCount.ets new file mode 100644 index 0000000..496c732 --- /dev/null +++ b/entry/src/main/ets/pages/PrefetchAndCacheCount.ets @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { router } from '@kit.ArkUI' + +@Entry +@Component +struct PrefetchAndCacheCount { + build() { + Column() { + Button('cacheCount == 5') + .onClick(()=>{ + router.pushUrl({url:'pages/LazyForEachCache'}) + }) + Button('cacheCount == 30') + .margin({top:10}) + .onClick(()=>{ + router.pushUrl({url:'pages/LazyForEachCount'}) + }) + Button('prefetch + preload') + .margin({top:10}) + .onClick(()=>{ + router.pushUrl({url:'pages/PrefetchAndPreload'}) + }) + }.width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/PrefetchAndPreload.ets b/entry/src/main/ets/pages/PrefetchAndPreload.ets new file mode 100644 index 0000000..0b29cf0 --- /dev/null +++ b/entry/src/main/ets/pages/PrefetchAndPreload.ets @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { BasicPrefetcher } from '@kit.ArkUI'; +import DataSourcePrefetchingImageKnife, { InfoItem } from './model/DataSourcePrefetching'; +import { PageViewModel } from './model/PageViewModel'; +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; +@Entry +@Component +export struct PrefetchAndPreload { + // 创建DataSourcePrefetchingImageKnife对象,具备任务预取、取消能力的数据源 + private readonly dataSource = new DataSourcePrefetchingImageKnife(PageViewModel.getItems()); + // 创建BasicPrefetcher对象,默认的动态预取算法实现 + private readonly prefetcher = new BasicPrefetcher(this.dataSource); + + build() { + Column() { + List({ space: 16 }) { + LazyForEach(this.dataSource, (item: InfoItem,index:number) => { + ListItem() { + Column({ space: 12 }) { + ImageKnifeComponent({ + imageKnifeOption:{ + loadSrc: item.albumUrl, + placeholderSrc:$r('app.media.loading') + } + }).width(100).height(100) + Text(`${index}`) + }.border({ width: 5 , color: '#000000'}) + } + .reuseId('imageKnife') + }) + } + .cachedCount(5) + .onScrollIndex((start: number, end: number) => { + // 列表滚动触发visibleAreaChanged,实时更新预取范围,触发调用prefetch、cancel接口 + this.prefetcher.visibleAreaChanged(start, end) + }) + .width('100%') + .height('100%') + .margin({ left: 10, right: 10 }) + .layoutWeight(1) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/SetMaxRequestPage.ets b/entry/src/main/ets/pages/SetMaxRequestPage.ets new file mode 100644 index 0000000..6ece0fe --- /dev/null +++ b/entry/src/main/ets/pages/SetMaxRequestPage.ets @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { router } from '@kit.ArkUI' + +@Entry +@Component +struct SetMaxRequestPage { + build() { + Column() { + Button('maxRequest = 8') + .onClick(()=>{ + router.pushUrl({url:'pages/MaxRequest1'}) + }) + Button('maxRequest = 20') + .onClick(()=>{ + router.pushUrl({url:'pages/MaxRequest2'}) + }).margin({top:20}) + Button('maxRequest = 32') + .onClick(()=>{ + router.pushUrl({url:'pages/MaxRequest2'}) + }).margin({top:20}) + }.width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/SignatureTestPage.ets b/entry/src/main/ets/pages/SignatureTestPage.ets index 8fc1763..6a314a6 100644 --- a/entry/src/main/ets/pages/SignatureTestPage.ets +++ b/entry/src/main/ets/pages/SignatureTestPage.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -16,18 +16,18 @@ import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; @Entry -@ComponentV2 +@Component struct SignatureTestPage { - @Local imageKnifeOption1: ImageKnifeOption =new ImageKnifeOption( + @State imageKnifeOption1: ImageKnifeOption = { loadSrc: $r('app.media.icon'), - placeholderSrc:$r("app.media.loading"), - }); - @Local imageKnifeOption2: ImageKnifeOption =new ImageKnifeOption( + placeholderSrc:$r('app.media.loading'), + }; + @State imageKnifeOption2: ImageKnifeOption = { loadSrc: $r('app.media.icon'), - placeholderSrc:$r("app.media.loading"), - }); + placeholderSrc:$r('app.media.loading'), + }; build() { Scroll() { @@ -37,11 +37,11 @@ struct SignatureTestPage { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Button($r('app.string.Load')) .onClick(() => { - this.imageKnifeOption1 = new ImageKnifeOption({ + this.imageKnifeOption1 = { loadSrc: 'https://img-blog.csdn.net/20140514114029140', - placeholderSrc:$r("app.media.loading"), - signature: "1" - }) + placeholderSrc:$r('app.media.loading'), + signature: '1' + } }).margin({ top: 5, left: 3 }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) }.width('100%').backgroundColor(Color.Pink) @@ -50,11 +50,11 @@ struct SignatureTestPage { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Button($r('app.string.Load')) .onClick(() => { - this.imageKnifeOption2 = new ImageKnifeOption({ + this.imageKnifeOption2 = { loadSrc: 'https://img-blog.csdn.net/20140514114029140', - placeholderSrc:$r("app.media.loading"), + placeholderSrc:$r('app.media.loading'), signature: new Date().getTime().toString() - }) + } }).margin({ top: 5, left: 3 }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300) }.width('100%').backgroundColor(Color.Pink) @@ -66,7 +66,7 @@ struct SignatureTestPage { } aboutToAppear() { - console.log("唯一标识页面:" + new Date().getTime().toString()) + console.log('唯一标识页面:' + new Date().getTime().toString()) } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/SingleImage.ets b/entry/src/main/ets/pages/SingleImage.ets index 3671c6c..50f723b 100644 --- a/entry/src/main/ets/pages/SingleImage.ets +++ b/entry/src/main/ets/pages/SingleImage.ets @@ -12,28 +12,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent,BlurTransformation,ImageKnifeOption } from '@ohos/libraryimageknife'; +import { ImageKnifeComponent,BlurTransformation } from '@ohos/libraryimageknife'; import fs from '@ohos.file.fs'; import image from '@ohos.multimedia.image'; import { common2D, drawing } from '@kit.ArkGraphics2D'; @Entry -@ComponentV2 +@Component struct SingleImage { - resource: string = "app.media.svgSample" + resource: string = 'app.media.svgSample' scroller: Scroller = new Scroller; - localFile: string = getContext(this).filesDir + "/icon.png" - @Local pixelMap:PixelMap | undefined = undefined; - @Local DrawingColorFilter: ColorFilter | undefined = undefined + localFile: string = getContext(this).filesDir + '/icon.png' + @State pixelMap:PixelMap | undefined = undefined; + @State DrawingColorFilter: ColorFilter | undefined = undefined private color: common2D.Color = { alpha: 255, red: 255, green: 0, blue: 0 }; aboutToAppear(): void { // 拷贝本地文件 - let icon: Uint8Array = getContext(this).resourceManager.getMediaContentSync($r("app.media.startIcon")); + let icon: Uint8Array = getContext(this).resourceManager.getMediaContentSync($r('app.media.startIcon')); let file = fs.openSync(this.localFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); fs.writeSync(file.fd, icon.buffer); fs.fsyncSync(file.fd); fs.closeSync(file); - this.changePic(getContext().resourceManager.getMediaContentSync( $r("app.media.aaa")) + this.changePic(getContext().resourceManager.getMediaContentSync( $r('app.media.aaa')) .buffer as ArrayBuffer); @@ -46,12 +46,12 @@ struct SingleImage { .fontSize(30) .fontWeight(FontWeight.Bold) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc: $r("app.media.svgSample"), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + imageKnifeOption: { + loadSrc: $r('app.media.svgSample'), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Contain - }) + } }).width(100).height(100) .onClick(()=>{ this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN); @@ -60,48 +60,54 @@ struct SingleImage { .fontSize(30) .fontWeight(FontWeight.Bold) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: this.localFile, - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Contain - }) + } }).width(100).height(100) Text($r('app.string.Network_images')) .fontSize(30) .fontWeight(FontWeight.Bold) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + imageKnifeOption: { + loadSrc:'https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png', + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Contain, - progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)} - }) + progressListener:(progress:number)=>{console.info('ImageKnife:: call back progress = ' + progress)}, + // 通过https协议进行连接时,默认使用系统预设CA证书。若希望使用自定义证书进行https连接,则需要将自定义证书上传至应用沙箱目录中,并在caPath中指定该证书所在的应用沙箱路径 + // caPath: '/data/storage/el1/bundle/ca.pem', + } }).width(100).height(100) Text($r('app.string.Custom_network_download')) .fontSize(30) .fontWeight(FontWeight.Bold) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg", - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + imageKnifeOption: { + loadSrc: 'https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg', + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Contain, + headerOption:[{ + key:'refer', + value:'xx.xx.xx.xx' + }], customGetImage: custom, transformation: new BlurTransformation(10) - }) + } }).width(100).height(100) Text($r('app.string.PixelMap_loads_images')) .fontSize(30) .fontWeight(FontWeight.Bold) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: this.pixelMap!, - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Contain, - }) + } }).width(100).height(100) } .width('100%') @@ -124,9 +130,11 @@ struct SingleImage { // 自定义下载方法 @Concurrent -async function custom(context: Context, src: string | PixelMap | Resource): Promise { - console.info("ImageKnife:: custom download:" + src) +async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record): Promise { + let refer = headers!['refer'] as string + console.info('ImageKnife:: custom download:' + src,'refer:'+refer) // 举例写死从本地文件读取,也可以自己请求网络图片 - return context.resourceManager.getMediaContentSync($r("app.media.startIcon").id).buffer as ArrayBuffer + let buffer = context.resourceManager.getMediaContentSync($r('app.media.startIcon').id).buffer as ArrayBuffer + return buffer } diff --git a/entry/src/main/ets/pages/TestCacheDataPage.ets b/entry/src/main/ets/pages/TestCacheDataPage.ets index e8da530..b70d7d6 100644 --- a/entry/src/main/ets/pages/TestCacheDataPage.ets +++ b/entry/src/main/ets/pages/TestCacheDataPage.ets @@ -13,35 +13,35 @@ * limitations under the License. */ -import { ImageKnife, CacheStrategy, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'; +import { ImageKnife, CacheStrategy, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; @Entry -@ComponentV2 +@Component struct TestCacheDataPage { - @Local cacheUpLimit: number = 0; - @Local currentNum: number = 0; - @Local currentSize: number = 0; - @Local currentWidth: number = 200 - @Local currentHeight: number = 200 - @Local markersLimitText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) - @Local markersNumText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) - @Local markersSizeText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) - @Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "", + @State cacheUpLimit: number = 0; + @State currentNum: number = 0; + @State currentSize: number = 0; + @State currentWidth: number = 200 + @State currentHeight: number = 200 + @State markersLimitText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) + @State markersNumText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) + @State markersSizeText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) + @State ImageKnifeOption: ImageKnifeOption = { + loadSrc: '', objectFit: ImageFit.Contain, onLoadListener: { onLoadFailed: (err) => { - console.error("Load Failed Reason: " + err); + console.error('Load Failed Reason: ' + err); }, onLoadSuccess: (data) => { return data; }, }, border: { radius: 50 } - }) + } aboutToAppear(): void { - ImageKnife.getInstance().initFileCache(getContext(this), 256, 256 * 1024 * 1024, "ImageKnifeCache1") + ImageKnife.getInstance().initFileCache(getContext(this), 256, 256 * 1024 * 1024, 'ImageKnifeCache1') } build() { @@ -55,21 +55,21 @@ struct TestCacheDataPage { Button($r('app.string.load_memory')) .onClick(() => { - this.ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg", + this.ImageKnifeOption = { + loadSrc: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg', objectFit: ImageFit.Contain, writeCacheStrategy: CacheStrategy.Memory, border: { radius: 50 }, - }) + } }) Button($r('app.string.load_disk')) .onClick(() => { - this.ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg", + this.ImageKnifeOption = { + loadSrc: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg', objectFit: ImageFit.Contain, writeCacheStrategy: CacheStrategy.File, border: { radius: 50 }, - }) + } }) Text($r('app.string.cur_cache_limit', this.markersLimitText, this.cacheUpLimit)) .fontSize(20) @@ -80,7 +80,7 @@ struct TestCacheDataPage { Text($r('app.string.cur_cache_size', this.markersSizeText, this.currentSize)).fontSize(20).margin({ bottom: 20 }); Button($r('app.string.get_cur_memory_limit')).onClick(() => { - let result = ImageKnife.getInstance().getCacheUpperLimit(CacheStrategy.Memory); + let result = ImageKnife.getInstance().getCacheLimitSize(CacheStrategy.Memory); this.markersLimitText = getContext(this).resourceManager.getStringSync($r('app.string.memory')) if (result) { this.cacheUpLimit = result / (1024 * 1024); @@ -89,7 +89,7 @@ struct TestCacheDataPage { } }).margin({ bottom: 8 }); Button($r('app.string.get_img_number_of_cache')).onClick(() => { - let result = ImageKnife.getInstance().getCurrentPicturesNum(CacheStrategy.Memory); + let result = ImageKnife.getInstance().getCurrentCacheNum(CacheStrategy.Memory); this.markersNumText = getContext(this).resourceManager.getStringSync($r('app.string.memory')) if (result) { this.currentNum = result; @@ -108,7 +108,7 @@ struct TestCacheDataPage { }).margin({ bottom: 8 }); Button($r('app.string.get_cur_disk_limit')).onClick(() => { - let result = ImageKnife.getInstance().getCacheUpperLimit(CacheStrategy.File); + let result = ImageKnife.getInstance().getCacheLimitSize(CacheStrategy.File); this.markersLimitText = getContext(this).resourceManager.getStringSync($r('app.string.disk')) if (result) { this.cacheUpLimit = result / (1024 * 1024); @@ -117,7 +117,7 @@ struct TestCacheDataPage { } }).margin({ bottom: 8 }); Button($r('app.string.get_img_number_of_disk')).onClick(() => { - let result = ImageKnife.getInstance().getCurrentPicturesNum(CacheStrategy.File); + let result = ImageKnife.getInstance().getCurrentCacheNum(CacheStrategy.File); this.markersNumText = getContext(this).resourceManager.getStringSync($r('app.string.disk')) if (result) { this.currentNum = result; diff --git a/entry/src/main/ets/pages/TestChangeColorPage.ets b/entry/src/main/ets/pages/TestChangeColorPage.ets index 2a282ae..2c89ac1 100644 --- a/entry/src/main/ets/pages/TestChangeColorPage.ets +++ b/entry/src/main/ets/pages/TestChangeColorPage.ets @@ -74,17 +74,17 @@ struct TestChangeColorPage { Text($r('app.string.master_image')).margin({ top: 20 }) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: this.src - }) + } }).width(110).height(110) Text($r('app.string.click_img_to_change_color')).margin({ top: 30 }) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: this.src, drawingColorFilter: this.DrawingColorFilterFirst - }) + } }) .onClick(() => { this.DrawingColorFilterFirst = @@ -93,18 +93,18 @@ struct TestChangeColorPage { Text($r('app.string.test_non_svg_color')).margin({ top: 30 }) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: $r('app.media.ic_test_change_color_png'), drawingColorFilter: drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN) - }) + } }).width(110).height(110) Text($r('app.string.test_svg_color')).margin({ top: 30 }) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc: $r("app.media.ic_test_change_color_svg"), + imageKnifeOption: { + loadSrc: $r('app.media.ic_test_change_color_svg'), drawingColorFilter: drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN) - }) + } }).width(110).height(110) }.width('100%').height('100%') diff --git a/entry/src/main/ets/pages/TestCommonImage.ets b/entry/src/main/ets/pages/TestCommonImage.ets index 66f3514..90aac0c 100644 --- a/entry/src/main/ets/pages/TestCommonImage.ets +++ b/entry/src/main/ets/pages/TestCommonImage.ets @@ -12,10 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent ,ImageKnifeOption} from '@ohos/libraryimageknife'; +import { ImageKnifeComponent } from '@ohos/libraryimageknife'; @Entry -@ComponentV2 +@Component struct TestCommonImage { private data: Array = [] aboutToAppear(): void { @@ -30,23 +30,23 @@ struct TestCommonImage { FlowItem() { Column(){ ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: item, - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.failed"), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), objectFit: ImageFit.Contain, - signature: "aaa" - }) - }).width("50%").height(200) + signature: 'aaa' + } + }).width('50%').height(200) } }.height(200) - .backgroundColor("#95efd2") + .backgroundColor('#95efd2') },(item: string) => item) - }.columnsTemplate("1fr 1fr") + }.columnsTemplate('1fr 1fr') .columnsGap(10) .rowsGap(5) .backgroundColor(0xFAEEE0) - .width("100%").height("100%") + .width('100%').height('100%') } } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/TestErrorHolderPage.ets b/entry/src/main/ets/pages/TestErrorHolderPage.ets index 0b716e2..0ade696 100644 --- a/entry/src/main/ets/pages/TestErrorHolderPage.ets +++ b/entry/src/main/ets/pages/TestErrorHolderPage.ets @@ -12,34 +12,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' +import { ImageKnifeComponent } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestErrorHolderPage { build() { Column() { - Text("ImageKnifeComponent1").fontSize(20) + Text('ImageKnifeComponent1').fontSize(20) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc: "abc", + imageKnifeOption: { + loadSrc: 'abc', errorholderSrc:$r('app.media.failed') - }) + } }).width(200).height(200) - Text("ImageKnifeComponent2").fontSize(20) + Text('ImageKnifeComponent2').fontSize(20) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc: "abc", + imageKnifeOption: { + loadSrc: 'abc', errorholderSrc:$r('app.media.startIcon') - }) + } }).width(200).height(200) - Text("ImageKnifeComponent2").fontSize(20) + Text('ImageKnifeComponent2').fontSize(20) ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ - loadSrc: "abc", + imageKnifeOption: { + loadSrc: 'abc', errorholderSrc:$r('app.media.mask_starfish') - }) + } }).width(200).height(200) } .height('100%') .width('100%') diff --git a/entry/src/main/ets/pages/TestHeader.ets b/entry/src/main/ets/pages/TestHeader.ets index 50027b0..27c5215 100644 --- a/entry/src/main/ets/pages/TestHeader.ets +++ b/entry/src/main/ets/pages/TestHeader.ets @@ -15,18 +15,18 @@ import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestPrefetchToFileCachePage { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ - loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + @State imageKnifeOption: ImageKnifeOption = { + loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', placeholderSrc:$r('app.media.loading'), headerOption:[ { - key:"abc", - value:"单个" + key:'abc', + value:'单个' } ] - }) + } build() { Column() { diff --git a/entry/src/main/ets/pages/TestHspPreLoadImage.ets b/entry/src/main/ets/pages/TestHspPreLoadImage.ets index e1084b8..1b21a6a 100644 --- a/entry/src/main/ets/pages/TestHspPreLoadImage.ets +++ b/entry/src/main/ets/pages/TestHspPreLoadImage.ets @@ -12,14 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { IndexComponent } from "@ohos/libraryimageknife" +import { IndexComponent } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestHspPreLoadImage { build() { Column() { - IndexComponent() - }.width("100%").height('100%') + IndexComponent() + }.width('100%').height('100%') } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/TestImageFlash.ets b/entry/src/main/ets/pages/TestImageFlash.ets index df2d363..6962cf6 100644 --- a/entry/src/main/ets/pages/TestImageFlash.ets +++ b/entry/src/main/ets/pages/TestImageFlash.ets @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' +import { ImageKnifeComponent } from '@ohos/libraryimageknife' -@ObservedV2 +@Observed export class MsgModel { id: string cId: string @@ -30,66 +30,66 @@ export class MsgModel { } -// @Reusable -@ComponentV2 +@Reusable +@Component export struct MsgItem { - @Param count: number = 0 + count: number = 0 private data: Array = [ - "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg", - "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg", - "http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg", - "http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg", - "http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg", - "http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg", - "http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg", - "http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg", - "http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg", - "http://f.hiphotos.baidu.com/image/pic/item/4034970a304e251f503521f5a586c9177e3e53f9.jpg", - "http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg", - "http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg", - "http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg", - "http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg", - "http://d.hiphotos.baidu.com/image/pic/item/b58f8c5494eef01f119945cbe2fe9925bc317d2a.jpg", - "http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg", - "http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg", - "http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg", - "http://b.hiphotos.baidu.com/image/pic/item/e824b899a9014c08878b2c4c0e7b02087af4f4a3.jpg", - "http://g.hiphotos.baidu.com/image/pic/item/6d81800a19d8bc3e770bd00d868ba61ea9d345f2.jpg", + 'http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg', + 'http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg', + 'http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg', + 'http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg', + 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg', + 'http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg', + 'http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg', + 'http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg', + 'http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg', + 'http://f.hiphotos.baidu.com/image/pic/item/4034970a304e251f503521f5a586c9177e3e53f9.jpg', + 'http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg', + 'http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg', + 'http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg', + 'http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg', + 'http://d.hiphotos.baidu.com/image/pic/item/b58f8c5494eef01f119945cbe2fe9925bc317d2a.jpg', + 'http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg', + 'http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg', + 'http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg', + 'http://b.hiphotos.baidu.com/image/pic/item/e824b899a9014c08878b2c4c0e7b02087af4f4a3.jpg', + 'http://g.hiphotos.baidu.com/image/pic/item/6d81800a19d8bc3e770bd00d868ba61ea9d345f2.jpg', ] build(){ if (this.count % 2 == 0 && this.count <6){ ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:$r("app.media.startIcon"), - placeholderSrc:$r("app.media.loading") - }),syncLoad:true + imageKnifeOption:{ + loadSrc:$r('app.media.startIcon'), + placeholderSrc:$r('app.media.loading') + },syncLoad:true }) }else if (this.count > 6 && this.count - 6 < this.data.length){ ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ + imageKnifeOption:{ loadSrc:this.data[this.count - 6], - placeholderSrc:$r("app.media.loading") - }),syncLoad:true + placeholderSrc:$r('app.media.loading') + },syncLoad:true }) }else { ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:$r("app.media.pngSample"), - placeholderSrc:$r("app.media.loading") - }),syncLoad:true + imageKnifeOption:{ + loadSrc:$r('app.media.pngSample'), + placeholderSrc:$r('app.media.loading') + },syncLoad:true }) } } } @Entry -@ComponentV2 +@Component struct ImageTestPage { count : number = 0 rCount: number = 0 scroller: Scroller = new Scroller() - @Local list: MsgModel[] = [] - @Local imageSize: number =100 + @State list: MsgModel[] = [] + @State imageSize: number =100 handAdd(){ this.count++ const msgItem = new MsgModel('add_id'+this.count, 'addBody'+this.count,'cId'+ this.count) @@ -103,10 +103,10 @@ struct ImageTestPage { build(){ Column(){ Row(){ - Button("addItem").onClick(()=> { + Button('addItem').onClick(()=> { this.handAdd() }) - Button("remove").onClick(()=> { + Button('remove').onClick(()=> { this.list.splice(0,1) }) } diff --git a/entry/src/main/ets/pages/TestImageKnifeCallbackPage.ets b/entry/src/main/ets/pages/TestImageKnifeCallbackPage.ets new file mode 100644 index 0000000..ae0abb4 --- /dev/null +++ b/entry/src/main/ets/pages/TestImageKnifeCallbackPage.ets @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ImageKnifeComponent, ImageKnifeData, ImageKnifeOption, ImageKnifeRequest } from '@ohos/libraryimageknife'; +import { router } from '@kit.ArkUI'; + +@Entry +@Component +struct TestImageKnifeCallbackPage { + @State imageKnifeOption: ImageKnifeOption = { + loadSrc: '', + objectFit: ImageFit.Contain, + border: { radius: 50 } + }; + @State currentWidth: number = 200 + @State currentHeight: number = 200 + @State url: string | undefined = '' + @State imageType: string | undefined = '' + @State imageWidth: number | undefined = 0 + @State imageHeight: number | undefined = 0 + @State imageSize: number | undefined = 0 + @State componentWidth: number | undefined = 0 + @State componentHeight: number | undefined = 0 + @State frameNum: number | undefined = 0 + @State decodeSize: string | undefined = '' + @State errMsg: string | undefined = '' + @State errPhase: string | undefined = '' + @State errCode: number | undefined = 0 + @State httpCode: number | undefined = 0 + @State reqStartTime: string | undefined = '' + @State reqEndTime: string | undefined = '' + @State reqCancelTime: string | undefined = '' + @State memoryStartTime: string | undefined = '' + @State memoryEndTime: string | undefined = '' + @State diskStartTime: string | undefined = '' + @State diskEndTime: string | undefined = '' + @State netStartTime: string | undefined = '' + @State netEndTime: string | undefined = '' + @State decodeStartTime: string | undefined = '' + @State decodeEndTime: string | undefined = '' + @State renderTime: string | undefined = '' + @State showChild: boolean = true; + + build() { + Column() { + Text($r('app.string.img_url', this.url)).fontSize(14) + Text($r('app.string.img_format', this.imageType)).fontSize(14) + Text($r('app.string.img_master_size', this.imageWidth, this.imageHeight, this.imageSize)).fontSize(14) + Text($r('app.string.componentWH', this.componentWidth, this.componentHeight)).fontSize(14) + Text($r('app.string.img_frame', this.frameNum)).fontSize(14) + Text($r('app.string.img_content_size', this.decodeSize)).fontSize(14) + Text($r('app.string.err_msg', this.errMsg)).fontSize(14) + Text($r('app.string.err_phase', this.errPhase)).fontSize(14) + Text($r('app.string.err_code', this.errCode)).fontSize(14) + Text($r('app.string.http_code', this.httpCode)).fontSize(14) + Text($r('app.string.req_start_time', this.reqStartTime)).fontSize(14) + Text($r('app.string.req_end_time', this.reqEndTime)).fontSize(14) + Text($r('app.string.req_cancel_time', this.reqCancelTime)).fontSize(14) + Text($r('app.string.memory_start_time', this.memoryStartTime)).fontSize(14) + Text($r('app.string.memory_end_time', this.memoryEndTime)).fontSize(14) + Text($r('app.string.disk_start_time', this.diskStartTime)).fontSize(14) + Text($r('app.string.disk_end_time', this.diskEndTime)).fontSize(14) + Text($r('app.string.net_start_time', this.netStartTime)).fontSize(14) + Text($r('app.string.net_end_time', this.netEndTime)).fontSize(14) + Text($r('app.string.decode_start_time', this.decodeStartTime)).fontSize(14) + Text($r('app.string.decode_end_time', this.decodeEndTime)).fontSize(14) + Text($r('app.string.render_time', this.renderTime)).fontSize(14) + + Scroll() { + Column() { + + Row() { + Button($r('app.string.Network_images')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg', + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + + Button($r('app.string.gif')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + Button($r('app.string.local_pic')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: $r('app.media.pngSample'), + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + } + + Row() { + Button($r('app.string.net_load_failed')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: 'https://img-blog.csdn.net/20140514114039140', + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + + Button($r('app.string.local_load_failed')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: 'app.media.xxx', + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + Button($r('app.string.share_load_failed')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: 'datashare://ssas', + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + } + + Button($r('app.string.test_cancel_callback_btn')) + .fontSize(13) + .onClick(() => { + this.destroy(); + this.imageKnifeOption = { + loadSrc: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg', + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + this.showChild = false; + this.analyzeStartCallBackData(data); + }, + onLoadFailed: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + }, + onLoadSuccess: (data, imageData, req) => { + this.analyzeSuccessCallBackData(req?.getImageKnifeData()); + }, + onLoadCancel: (res, req) => { + this.analyzeFailedBackData(res, req?.getImageKnifeData()); + } + }, + border: { radius: 50 }, + onComplete: (event) => { + if (event && event.loadingStatus == 0) { + this.renderTime = this.formatDate(Date.now()); + } + } + } + }) + + Button($r('app.string.list_pic')) + .fontSize(13) + .onClick(() => { + router.push({ + url: 'pages/TestListImageKnifeCallbackPage', + }); + }) + if (this.showChild) { + ImageKnifeComponent( + { imageKnifeOption: this.imageKnifeOption }) + .height(this.currentHeight) + .width(this.currentWidth) + .margin({ top: 20, bottom: 20 }) + + } + } + .width('100%') + } + }.alignItems(HorizontalAlign.Start) + } + + formatDate(time: number | undefined) { + if (!time) { + return; + } + let date = new Date(time); + const year = date.getFullYear().toString() + let month = (date.getMonth() + 1).toString() + let day = date.getDate().toString() + let hour = date.getHours().toString() + let min = date.getMinutes().toString() + let seconds = date.getSeconds().toString() + let mill = date.getMilliseconds(); + return `${year}-${month}-${day} ${hour}:${min}:${seconds}:${mill}` + } + + analyzeStartCallBackData(req: ImageKnifeRequest | undefined) { + let data = req?.getImageKnifeData(); + if (data) { + if (typeof req?.imageKnifeOption.loadSrc == 'string') { + this.url = req?.imageKnifeOption.loadSrc; + } + this.componentWidth = req?.componentWidth; + this.componentHeight = req?.componentHeight; + this.reqStartTime = this.formatDate(data.timeInfo?.requestStartTime); + this.memoryStartTime = this.formatDate(data.timeInfo?.memoryCheckStartTime); + this.memoryEndTime = this.formatDate(data.timeInfo?.memoryCheckEndTime); + } + } + + analyzeSuccessCallBackData(data: ImageKnifeData | undefined) { + if (data) { + this.imageWidth = data.imageWidth; + this.imageHeight = data.imageHeight; + this.imageSize = data.bufSize; + this.frameNum = data.frameCount; + this.decodeSize = JSON.stringify(data.decodeImages); + this.imageType = data.type; + this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime); + this.diskStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime); + this.diskEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime); + this.netStartTime = this.formatDate(data.timeInfo?.netRequestStartTime); + this.netEndTime = this.formatDate(data.timeInfo?.netRequestEndTime); + this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime); + this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime); + } + } + + analyzeFailedBackData(res: string, data: ImageKnifeData | undefined) { + if (data) { + this.errMsg = res; + this.errPhase = data.errorInfo?.phase; + this.errCode = data.errorInfo?.code; + this.httpCode = data.errorInfo?.httpCode; + this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime); + this.diskStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime); + this.diskEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime); + this.netStartTime = this.formatDate(data.timeInfo?.netRequestStartTime); + this.netEndTime = this.formatDate(data.timeInfo?.netRequestEndTime); + this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime); + this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime); + this.reqCancelTime = this.formatDate(data.timeInfo?.requestCancelTime) + } + } + + destroy() { + this.currentWidth = 200 + this.currentHeight = 200 + this.url = '' + this.imageType = '' + this.imageWidth = 0 + this.imageHeight = 0 + this.imageSize = 0 + this.componentWidth = 0 + this.componentHeight = 0 + this.frameNum = 0 + this.decodeSize = '' + this.errMsg = '' + this.errPhase = '' + this.errCode = 0 + this.httpCode = 0 + this.reqStartTime = '' + this.reqEndTime = '' + this.reqCancelTime = '' + this.memoryStartTime = '' + this.memoryEndTime = '' + this.diskStartTime = '' + this.diskEndTime = '' + this.netStartTime = '' + this.netEndTime = '' + this.decodeStartTime = '' + this.decodeEndTime = '' + this.renderTime = '' + this.showChild = true; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/TestIsUrlExist.ets b/entry/src/main/ets/pages/TestIsUrlExist.ets index da91f54..72cfee4 100644 --- a/entry/src/main/ets/pages/TestIsUrlExist.ets +++ b/entry/src/main/ets/pages/TestIsUrlExist.ets @@ -15,37 +15,37 @@ import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestIsUrlExist { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon'), placeholderSrc: $r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }) - @Local source: PixelMap | string | Resource = $r("app.media.startIcon") - @Local source1: PixelMap | string | Resource = $r("app.media.startIcon") + } + @State source: PixelMap | string | Resource = $r('app.media.startIcon') + @State source1: PixelMap | string | Resource = $r('app.media.startIcon') build() { Column() { Flex() { Button($r('app.string.Preloading_GIF')).onClick(() => { this.imageKnifeOption.loadSrc = - "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658" + 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658' }) Button($r('app.string.Retrieve_GIF_from_memory')).onClick(() => { ImageKnife.getInstance() - .getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + .getCacheImage('https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', CacheStrategy.Memory) .then((data) => { - this.source = data !== undefined ? data.source : $r("app.media.startIcon") + this.source = data !== undefined ? data.source : $r('app.media.startIcon') }) }) Button($r('app.string.Retrieve_GIF_from_disk')).onClick(() => { ImageKnife.getInstance() - .getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + .getCacheImage('https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', CacheStrategy.File) .then((data) => { - this.source1 = data !== undefined ? data.source : $r("app.media.startIcon") + this.source1 = data !== undefined ? data.source : $r('app.media.startIcon') }) }) } diff --git a/entry/src/main/ets/pages/TestListImageKnifeCallbackPage.ets b/entry/src/main/ets/pages/TestListImageKnifeCallbackPage.ets new file mode 100644 index 0000000..32bc631 --- /dev/null +++ b/entry/src/main/ets/pages/TestListImageKnifeCallbackPage.ets @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ImageKnifeComponent} from '@ohos/libraryimageknife'; + +class ArrayElement { + public src: string = ''; + public w: number = 0; + public h: number = 0; +} + +@Entry +@Component +struct TestListImageKnifeCallbackPage { + private wid: number = 200; + private hig: number = 200; + private dataArray: ESObject[] = [ + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg', + 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg', + 'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg', + 'https://img-blog.csdn.net/20140514114029140', + 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', + $r('app.media.pngSample'), + $r('app.media.rabbit') + ] + private data: Array = []; + + aboutToAppear(): void { + for (let i = 0; i < this.dataArray.length; i++) { + let element: ArrayElement = { + src: this.dataArray[i], + w: this.wid -(i*5), + h: this.hig -(i*5) + } + this.data.push(element); + } + } + + build() { + List({ space: 3 }) { + ForEach(this.data, (item: ArrayElement) => { + ListItem() { + ImageKnifeComponent({ + imageKnifeOption: + { + loadSrc: item.src, + objectFit: ImageFit.Contain, + onLoadListener: { + onLoadStart: (data) => { + console.log('listCache start:{ url:' + data?.imageKnifeOption.loadSrc + + ',componentWidth:' + data?.componentWidth + + ',componentHeight:' + data?.componentHeight + + '},' + JSON.stringify(data?.getImageKnifeData())) + }, + onLoadFailed: (res, req) => { + console.log('listCache onLoadFailed:res:' + res + ';' + JSON.stringify(req?.getImageKnifeData())) + }, + onLoadSuccess: (data, imageData,req) => { + console.log('listCache onLoadSuccess:' + JSON.stringify(req?.getImageKnifeData())) + }, + onLoadCancel: (res, req) => { + console.log('listCache onLoadCancel:res:' + res + ';' + JSON.stringify(req?.getImageKnifeData())) + } + }, + border: { radius: 50 }, + } + }).height(item.w).width(item.h) + }.width('100%') + }, (item: ArrayElement,index) => (item.src+index)) + }.width('100%').height('100%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/TestLoadCancelListenerPage.ets b/entry/src/main/ets/pages/TestLoadCancelListenerPage.ets index 5e97810..dd90c4b 100644 --- a/entry/src/main/ets/pages/TestLoadCancelListenerPage.ets +++ b/entry/src/main/ets/pages/TestLoadCancelListenerPage.ets @@ -13,20 +13,21 @@ * limitations under the License. */ -import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'; +import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; + @Entry -@ComponentV2 +@Component struct TestLoadCancelListenerPage { - @Local currentWidth: number = 200 - @Local currentHeight: number = 200 - @Local showChild: boolean = true; - @Local text: string = ""; - @Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "", + @State currentWidth: number = 200 + @State currentHeight: number = 200 + @State showChild: boolean = true; + @State text: string = ''; + @State ImageKnifeOption: ImageKnifeOption = { + loadSrc: '', objectFit: ImageFit.Contain, border: { radius: 50 } - }) + }; build() { Column() { @@ -34,8 +35,9 @@ struct TestLoadCancelListenerPage { Button($r('app.string.rm_component_of_net')) .margin(20) .onClick(() => { - this.ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg", + this.clearCache(); + this.ImageKnifeOption = { + loadSrc: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg', objectFit: ImageFit.Contain, onLoadListener: { onLoadStart: () => { @@ -43,27 +45,28 @@ struct TestLoadCancelListenerPage { }, onLoadCancel: (res) => { this.text = res - console.log("TestLoadCancelListenerPage----onLoadCancel> url:" + res) + console.log('TestLoadCancelListenerPage----onLoadCancel> url:' + res) } }, border: { radius: 50 } - }) + } }) Button($r('app.string.component_display')) .margin(20).onClick(() => { - this.text = ""; + this.text = ''; this.showChild = true; - this.ImageKnifeOption = new ImageKnifeOption({ - loadSrc: "", + this.ImageKnifeOption = { + loadSrc: '', objectFit: ImageFit.Contain, border: { radius: 50 } - }) + } }) Button($r('app.string.rm_component_of_local')) .margin(20) .onClick(() => { - this.ImageKnifeOption = new ImageKnifeOption({ + this.clearCache(); + this.ImageKnifeOption = { loadSrc: $r('app.media.loading'), objectFit: ImageFit.Contain, onLoadListener: { @@ -72,11 +75,11 @@ struct TestLoadCancelListenerPage { }, onLoadCancel: (res) => { this.text = res - console.log("TestLoadCancelListenerPage----onLoadCancel> url:" + res) + console.log('TestLoadCancelListenerPage----onLoadCancel> url:' + res) } }, border: { radius: 50 } - }) + } }) if (this.showChild) { @@ -91,4 +94,8 @@ struct TestLoadCancelListenerPage { .height('100%') .width('100%') } + + clearCache(){ + ImageKnife.getInstance().removeAllMemoryCache(); + } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/TestPrefetchToFileCache.ets b/entry/src/main/ets/pages/TestPrefetchToFileCache.ets index c541bd1..1fed2a3 100644 --- a/entry/src/main/ets/pages/TestPrefetchToFileCache.ets +++ b/entry/src/main/ets/pages/TestPrefetchToFileCache.ets @@ -15,31 +15,31 @@ import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestPrefetchToFileCachePage { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc:$r('app.media.startIcon'), placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }) + } async preload(url:string) { let fileCachePath = await ImageKnife.getInstance().preLoadCache(url) - console.log("preload-fileCachePath=="+ fileCachePath) + console.log('preload-fileCachePath=='+ fileCachePath) } async preload1(url:string) { - let fileCachePath = await ImageKnife.getInstance().preLoadCache(new ImageKnifeOption({ loadSrc: url })) - console.log("preload-fileCachePath1=="+ fileCachePath) + let fileCachePath = await ImageKnife.getInstance().preLoadCache({ loadSrc: url }) + console.log('preload-fileCachePath1=='+ fileCachePath) } build() { Column() { Button($r('app.string.Preloading_images_to_file_cache_using_URL')).margin({top:10}).onClick(async ()=>{ - await this.preload("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658") + await this.preload('https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658') }) Button($r('app.string.Preloading_images_to_file_cache_using_option')).margin({top:10}).onClick(async ()=>{ - await this.preload1("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658") + await this.preload1('https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658') }) Button($r('app.string.Load_image_offline_after_preloading')).margin({top:10}).onClick(()=>{ - this.imageKnifeOption.loadSrc = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658" + this.imageKnifeOption.loadSrc = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658' }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption diff --git a/entry/src/main/ets/pages/TestRemoveCache.ets b/entry/src/main/ets/pages/TestRemoveCache.ets index aadfc5a..3bfcd86 100644 --- a/entry/src/main/ets/pages/TestRemoveCache.ets +++ b/entry/src/main/ets/pages/TestRemoveCache.ets @@ -15,40 +15,40 @@ import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestRemoveCache { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon'), placeholderSrc: $r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }) - @Local source: PixelMap | string | Resource = $r("app.media.startIcon"); - @Local source1: PixelMap | string | Resource = $r("app.media.startIcon"); - @Local url: string = ''; + } + @State source: PixelMap | string | Resource = $r('app.media.startIcon'); + @State source1: PixelMap | string | Resource = $r('app.media.startIcon'); + @State url: string = ''; build() { Column() { Flex() { Button($r('app.string.Preloading_GIF')).onClick(() => { - this.imageKnifeOption.loadSrc = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658"; - this.url = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658"; + this.imageKnifeOption.loadSrc = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658'; + this.url = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658'; }) .margin({left:10}) Button($r('app.string.Retrieve_GIF_from_memory')).onClick(() => { ImageKnife.getInstance() - .getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + .getCacheImage('https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', CacheStrategy.Memory) .then((data) => { - this.source = data !== undefined ? data.source : $r("app.media.startIcon"); + this.source = data !== undefined ? data.source : $r('app.media.startIcon'); }) }) .margin({left:10}) Button($r('app.string.Retrieve_GIF_from_disk')).onClick(() => { ImageKnife.getInstance() - .getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", + .getCacheImage('https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', CacheStrategy.File) .then((data) => { - this.source1 = data !== undefined ? data.source : $r("app.media.startIcon"); + this.source1 = data !== undefined ? data.source : $r('app.media.startIcon'); }) }) .margin({left:10}) diff --git a/entry/src/main/ets/pages/TestSetCustomImagePage.ets b/entry/src/main/ets/pages/TestSetCustomImagePage.ets index 58a5c7b..350529f 100644 --- a/entry/src/main/ets/pages/TestSetCustomImagePage.ets +++ b/entry/src/main/ets/pages/TestSetCustomImagePage.ets @@ -15,55 +15,54 @@ import { ImageKnifeComponent, ImageKnife, ImageKnifeOption } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestSetCustomImagePage { - - getResourceString(res:Resource){ - return getContext().resourceManager.getStringSync(res.id) - } - - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon'), placeholderSrc: $r('app.media.loading') - }) + } aboutToAppear(): void { ImageKnife.getInstance().setCustomGetImage(custom) } aboutToDisappear(): void { ImageKnife.getInstance().setCustomGetImage() } + getResourceString(res:Resource){ + return getContext().resourceManager.getStringSync(res.id) + } build() { Column() { - Button(this.getResourceString($r('app.string.Custom_network_download')) + " a").onClick(()=>{ - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: "aaa", + Button(this.getResourceString($r('app.string.Custom_network_download')) + ' a').onClick(()=>{ + this.imageKnifeOption ={ + loadSrc: 'aaa', placeholderSrc: $r('app.media.loading') - }) + } }) - Button(this.getResourceString($r('app.string.Custom_network_download')) + " b").onClick(()=>{ - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: "bbb", + Button(this.getResourceString($r('app.string.Custom_network_download')) + ' b').onClick(()=>{ + this.imageKnifeOption = { + loadSrc: 'bbb', placeholderSrc: $r('app.media.loading') - }) + } }) - Button(this.getResourceString($r('app.string.Custom_network_download')) + " c").onClick(()=>{ - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: "ccc", + Button(this.getResourceString($r('app.string.Custom_network_download')) + ' c').onClick(()=>{ + this.imageKnifeOption = { + loadSrc: 'ccc', placeholderSrc: $r('app.media.loading') - }) + } }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }).width(300) .height(300) } - .width("100%") - .height("100%") + .width('100%') + .height('100%') } } @Concurrent -async function custom(context: Context, src: string | PixelMap | Resource): Promise { - console.info("ImageKnife:: custom download:" + src) +async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record): Promise { + console.info('ImageKnife:: custom download:' + src) // 举例写死从本地文件读取,也可以自己请求网络图片 - return context.resourceManager.getMediaContentSync($r("app.media.pngSample").id).buffer as ArrayBuffer + let buffer = context.resourceManager.getMediaContentSync($r('app.media.pngSample').id).buffer as ArrayBuffer + return buffer } \ No newline at end of file diff --git a/entry/src/main/ets/pages/TestTaskResourcePage.ets b/entry/src/main/ets/pages/TestTaskResourcePage.ets index d5dc143..6289a6e 100644 --- a/entry/src/main/ets/pages/TestTaskResourcePage.ets +++ b/entry/src/main/ets/pages/TestTaskResourcePage.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife" +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' @ComponentV2 export struct ZuImage { @@ -24,12 +24,12 @@ export struct ZuImage { if (this.src) { //当前版本存在bug ImageKnifeComponent({ - imageKnifeOption: new ImageKnifeOption({ + imageKnifeOption: { loadSrc: this.src, placeholderSrc: this.placeholderSrc, errorholderSrc: this.errorholderSrc ?? this.placeholderSrc, objectFit: ImageFit.Cover - }) + } }) } else { Image(this.placeholderSrc) @@ -43,7 +43,7 @@ export struct ZuImage { @ComponentV2 struct TestTaskResourcePage { @Local stateMenus: Array = [ - "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", + 'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB', 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg', 'https://img-blog.csdn.net/20140514114029140', 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', @@ -53,7 +53,7 @@ struct TestTaskResourcePage { Column({ space: 8 }) { ZuImage({ src: item, - placeholderSrc: $r("app.media.loading") + placeholderSrc: $r('app.media.loading') }).width(44) .height(44) } @@ -66,7 +66,7 @@ struct TestTaskResourcePage { this._buildItem(item) } }) - }.width("100%") + }.width('100%') .columnsTemplate('1fr 1fr 1fr 1fr 1fr') .rowsGap(24) .padding({ diff --git a/entry/src/main/ets/pages/TestWriteCacheStage.ets b/entry/src/main/ets/pages/TestWriteCacheStage.ets index a5f0431..4f34f9f 100644 --- a/entry/src/main/ets/pages/TestWriteCacheStage.ets +++ b/entry/src/main/ets/pages/TestWriteCacheStage.ets @@ -15,55 +15,55 @@ import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/libraryimageknife' @Entry -@ComponentV2 +@Component struct TestWriteCacheStage { - @Local imageKnifeOption1: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption1: ImageKnifeOption = { loadSrc:$r('app.media.startIcon'), placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }) - @Local imageKnifeOption2: ImageKnifeOption = new ImageKnifeOption({ + } + @State imageKnifeOption2: ImageKnifeOption = { loadSrc:$r('app.media.startIcon'), placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }) - @Local imageKnifeOption3: ImageKnifeOption = new ImageKnifeOption({ + } + @State imageKnifeOption3: ImageKnifeOption = { loadSrc:$r('app.media.startIcon'), placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed') - }) + } build() { Column() { Button($r('app.string.Write_memory_and_file')).margin({top:10}).onClick(async ()=>{ - this.imageKnifeOption1 = new ImageKnifeOption({ + this.imageKnifeOption1 = { loadSrc:'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed'), writeCacheStrategy:CacheStrategy.Default - }) + } }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(200).height(200).margin({top:10}) Button($r('app.string.Write_memory')).margin({top:10}).onClick(async ()=>{ - this.imageKnifeOption2 = new ImageKnifeOption({ - loadSrc:"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", + this.imageKnifeOption2 = { + loadSrc:'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed'), writeCacheStrategy:CacheStrategy.Memory - }) + } }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(200).height(200).margin({top:10}) Button($r('app.string.Write_file')).margin({top:10}).onClick(async ()=>{ - this.imageKnifeOption3 = new ImageKnifeOption({ + this.imageKnifeOption3 = { loadSrc:'https://img-blog.csdn.net/20140514114029140', placeholderSrc:$r('app.media.loading'), errorholderSrc:$r('app.media.failed'), writeCacheStrategy:CacheStrategy.File - }) + } }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption3 diff --git a/entry/src/main/ets/pages/TransformPage.ets b/entry/src/main/ets/pages/TransformPage.ets index 0288c1d..d5dcdbe 100644 --- a/entry/src/main/ets/pages/TransformPage.ets +++ b/entry/src/main/ets/pages/TransformPage.ets @@ -12,22 +12,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife" +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' import matrix4 from '@ohos.matrix4' @Entry -@ComponentV2 +@Component struct TransformPage { private custom_scale:number = 1 - @Local matrix1:object = matrix4.identity().scale({ x: 1, y: 1 }) - @Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ - loadSrc: $r("app.media.rabbit"), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), + @State matrix1:object = matrix4.identity().scale({ x: 1, y: 1 }) + @State ImageKnifeOption: ImageKnifeOption = { + loadSrc: $r('app.media.rabbit'), + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.app_icon'), objectFit: ImageFit.Contain, border: { radius: 50 } - }) + } build() { Column() { diff --git a/entry/src/main/ets/pages/User.ets b/entry/src/main/ets/pages/User.ets index 603b767..6bfd1ef 100644 --- a/entry/src/main/ets/pages/User.ets +++ b/entry/src/main/ets/pages/User.ets @@ -15,50 +15,24 @@ import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' // const logger = new imUtils.logger.IMLogger('Avatar') -@ObservedV2 -export class MyStorage { - static instance:MyStorage | undefined = undefined - static getInstance(){ - if(MyStorage.instance == undefined) { - MyStorage.instance = new MyStorage() - } - return MyStorage.instance - } - @Trace WeLink_Mob_fontSize_multiple: number = 1 + +class MyImageOption extends ImageKnifeOption { + account?: string } -@ComponentV2 +@Component export struct UserAvatar { - // @Prop userInfo: string = "" + @Prop @Watch('userInfoUpdate') userInfo: string = '' + // @Prop userInfo: string = '' imgSize: number = 100 radius: number = 12 borderSize: number = 0 imgSizes: number = 1 - @Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption() + @State ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption() + @StorageProp('WeLink_Mob_fontSize_multiple') @Watch('updateImgSize') WeLink_Mob_fontSize_multiple: number = 0 scalable: boolean = true; - @Local calcImgSize: number = 100 - @Param userInfo: string = "" - @Monitor('userInfo') - userInfoUpdate() { - // if (uri === 'userInfo' && this.imageKnifeOption.account !== this.userInfo.contactId) return; - // // logger.info(`userInfoUpdate uri=${uri} oldAcc=${this.imageKnifeOption.loadSrc} nowAcc=${this.userInfo.externalHeadUrl}`) - // if (this.userInfo.externalHeadUrl === this.imageKnifeOption.loadSrc && this.userInfo.infoUpdateTime.getTime() - // .toString() === this.imageKnifeOption?.signature?.getKey()) return; - this.ImageKnifeOption = new ImageKnifeOption({ - //TODO:写死loadSRC,场景:变更组件大小,所有图片不显示 - loadSrc: this.userInfo, - placeholderSrc: $r('app.media.loading'), - errorholderSrc: $r('app.media.failed'), - border: { radius:20,width:5,color:$r('app.color.start_window_background') }, - objectFit:ImageFit.Contain - // signature: new ObjectKey(this.userInfo.infoUpdateTime.getTime().toString()) - }) - } - @Local storage: MyStorage = MyStorage.getInstance() - @Monitor('storage.WeLink_Mob_fontSize_multiple') - updateImgSize() { - this.setImageSize() - } + @State calcImgSize: number = 100 + aboutToAppear(): void { this.userInfoUpdate() this.setImageSize() @@ -67,19 +41,39 @@ export struct UserAvatar { setImageSize() { if (!this.scalable) { this.calcImgSize = this.imgSize - } else if (this.storage.WeLink_Mob_fontSize_multiple < 0.9) { + } else if (this.WeLink_Mob_fontSize_multiple < 0.9) { this.calcImgSize = this.imgSize * 0.9 - } else if (this.storage.WeLink_Mob_fontSize_multiple > 1.6) { + } else if (this.WeLink_Mob_fontSize_multiple > 1.6) { this.calcImgSize = this.imgSize * 1.6 } else { - this.calcImgSize = this.imgSize * this.storage.WeLink_Mob_fontSize_multiple + this.calcImgSize = this.imgSize * this.WeLink_Mob_fontSize_multiple } } + updateImgSize() { + this.setImageSize() + } + aboutToReuse(param: ESObject) { this.userInfoUpdate() } + userInfoUpdate() { + // if (uri === 'userInfo' && this.imageKnifeOption.account !== this.userInfo.contactId) return; + // // logger.info(`userInfoUpdate uri=${uri} oldAcc=${this.imageKnifeOption.loadSrc} nowAcc=${this.userInfo.externalHeadUrl}`) + // if (this.userInfo.externalHeadUrl === this.imageKnifeOption.loadSrc && this.userInfo.infoUpdateTime.getTime() + // .toString() === this.imageKnifeOption?.signature?.getKey()) return; + this.ImageKnifeOption = { + //TODO:写死loadSRC,场景:变更组件大小,所有图片不显示 + loadSrc: this.userInfo, + placeholderSrc: $r('app.media.loading'), + errorholderSrc: $r('app.media.failed'), + border: { radius:20,width:5,color:$r('app.color.start_window_background') }, + objectFit:ImageFit.Contain + // signature: new ObjectKey(this.userInfo.infoUpdateTime.getTime().toString()) + } + } + build() { Row() { // Image(this.imageKnifeOption.loadSrc) @@ -93,12 +87,12 @@ export struct UserAvatar { - // Image(this.userInfo) - // Text((this.imageKnifeOption.loadSrc as string).split('/')[8]) - // .position({ x: 0, y: 0 }) - // .zIndex(9) - // .fontSize(12) - // .fontColor('#ff0000') + // Image(this.userInfo) + // Text((this.imageKnifeOption.loadSrc as string).split('/')[8]) + // .position({ x: 0, y: 0 }) + // .zIndex(9) + // .fontSize(12) + // .fontColor('#ff0000') } } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/UserPage.ets b/entry/src/main/ets/pages/UserPage.ets index 92d1caf..01de99b 100644 --- a/entry/src/main/ets/pages/UserPage.ets +++ b/entry/src/main/ets/pages/UserPage.ets @@ -12,138 +12,83 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { MyStorage, UserAvatar } from './User' +import { CommonDataSource } from './model/CommonDataSource' +import { UserAvatar } from './User' -class CommonDataSource implements IDataSource { - private dataArray: T[] = [] - private listeners: DataChangeListener[] = [] - - constructor(element: []) { - this.dataArray = element - } - - public getData(index: number) { - return this.dataArray[index] - } - - public totalCount(): number { - return this.dataArray.length - } - - public addData(index: number, data: T[]): void { - this.dataArray = this.dataArray.concat(data) - this.notifyDataAdd(index) - } - - unregisterDataChangeListener(listener: DataChangeListener): void { - const pos = this.listeners.indexOf(listener); - if (pos >= 0) { - this.listeners.splice(pos, 1); - } - } - - registerDataChangeListener(listener: DataChangeListener): void { - if (this.listeners.indexOf(listener) < 0) { - this.listeners.push(listener) - } - } - - notifyDataAdd(index: number): void { - this.listeners.forEach((listener: DataChangeListener) => { - listener.onDataAdd(index) - }) - } -} @Entry -@ComponentV2 +@Component struct Index { - @Local hotCommendList:CommonDataSource = new CommonDataSource([]) + @State hotCommendList:CommonDataSource = new CommonDataSource([]) private data:string[] = [ - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/42/v3/2dSQCqERTP2TTPyssOMEbQ/zL1ebnKKQ_ilqTDcwCAkOw.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg", - "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg", - "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/42/v3/2dSQCqERTP2TTPyssOMEbQ/zL1ebnKKQ_ilqTDcwCAkOw.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg', + 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg', + 'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB', 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg', 'https://img-blog.csdn.net/20140514114029140', 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', ] aboutToAppear(): void { - MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 1 + this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data) + AppStorage.set('WeLink_Mob_fontSize_multiple',1) } build() { Column() { - Button("bigger").onClick(()=>{ - MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 1.6 + Button('bigger').onClick(()=>{ + AppStorage.set('WeLink_Mob_fontSize_multiple',1.6) }) - Button("small").onClick(()=>{ - MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 0.8 + Button('small').onClick(()=>{ + AppStorage.set('WeLink_Mob_fontSize_multiple',0.8) }) List(){ - // LazyForEach(this.hotCommendList,(item:string)=>{ - // ListItem(){ - // ReuseImage({ - // userInfo:item - // }).width("100%").height("100%").backgroundColor(Color.Yellow) - // }.width(200).height(200).margin({bottom:5}) - // }) - Repeat(this.data) - .each((repeatItem)=>{ - ListItem(){ - ReuseImage({ - userInfo:repeatItem.item - }).width("100%").height("100%").backgroundColor(Color.Yellow) - }.width(200).height(200).margin({bottom:5}).key("reuse") - }) - .key(item => item+"reuse") - .virtualScroll() - .template("1",(repeatItem)=>{ - ListItem(){ - ReuseImage({ - userInfo:repeatItem.item - }).width("100%").height("100%").backgroundColor(Color.Yellow) - }.width(200).height(200).margin({bottom:5}).key("reuse") - }) + LazyForEach(this.hotCommendList,(item:string)=>{ + ListItem(){ + ReuseImage({ + userInfo:item + }).width('100%').height('100%').backgroundColor(Color.Yellow) + }.width(200).height(200).margin({bottom:5}) + }) } // .cachedCount(20) - .width("100%") - .height("100%") + .width('100%') + .height('100%') .backgroundColor(0xFAEEE0) - }.width('100%').height("100%") + }.width('100%').height('100%') } } -// @Reusable -@ComponentV2 +@Reusable +@Component struct ReuseImage { - @Param userInfo:string = "" - // aboutToReuse(params: ESObject): void { - // this.userInfo = params.userInfo - // } + @State userInfo:string = '' + aboutToReuse(params: ESObject): void { + this.userInfo = params.userInfo + } build() { Column(){ UserAvatar({ userInfo:this.userInfo }) - }.width("100%").height("100%") + }.width('100%').height('100%') } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/dataShareUriLoadPage.ets b/entry/src/main/ets/pages/dataShareUriLoadPage.ets index 7392044..b7b5b0a 100644 --- a/entry/src/main/ets/pages/dataShareUriLoadPage.ets +++ b/entry/src/main/ets/pages/dataShareUriLoadPage.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -18,15 +18,15 @@ import { photoAccessHelper } from '@kit.MediaLibraryKit'; @Entry -@ComponentV2 +@Component struct DataShareUriLoadPage { - @Local imageKnifeOption1: ImageKnifeOption = - new ImageKnifeOption({ + @State imageKnifeOption1: ImageKnifeOption = + { loadSrc: $r('app.media.icon'), placeholderSrc: $r('app.media.loading'), errorholderSrc: $r('app.media.failed') - }); + }; build() { @@ -43,10 +43,10 @@ struct DataShareUriLoadPage { let photoViewPicker = new photoAccessHelper.PhotoViewPicker(); let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions); uris = photoSelectResult.photoUris; - this.imageKnifeOption1 = new ImageKnifeOption({ + this.imageKnifeOption1 = { loadSrc: uris[0], placeholderSrc:$r('app.media.loading') - }) + } }).margin({ top: 5, left: 3 }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) }.width('100%').backgroundColor(Color.Pink) diff --git a/entry/src/main/ets/pages/model/CommonDataSource.ets b/entry/src/main/ets/pages/model/CommonDataSource.ets new file mode 100644 index 0000000..fd2b050 --- /dev/null +++ b/entry/src/main/ets/pages/model/CommonDataSource.ets @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class CommonDataSource implements IDataSource { + private dataArray: T[] = [] + private listeners: DataChangeListener[] = [] + + constructor(element: []) { + this.dataArray = element + } + + public getData(index: number) { + return this.dataArray[index] + } + + public totalCount(): number { + return this.dataArray.length + } + + public addData(index: number, data: T[]): void { + this.dataArray = this.dataArray.concat(data) + this.notifyDataAdd(index) + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener) + } + } + + notifyDataAdd(index: number): void { + this.listeners.forEach((listener: DataChangeListener) => { + listener.onDataAdd(index) + }) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/model/DataSourcePrefetching.ets b/entry/src/main/ets/pages/model/DataSourcePrefetching.ets new file mode 100644 index 0000000..3726d63 --- /dev/null +++ b/entry/src/main/ets/pages/model/DataSourcePrefetching.ets @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {ImageKnife, ImageKnifeRequest} from '@ohos/libraryimageknife' +import { IDataSourcePrefetching } from '@kit.ArkUI'; +import { HashMap } from '@kit.ArkTS'; + +const IMADE_UNAVAILABLE = $r('app.media.failed') +export interface InfoItem { + albumUrl: string | Resource +} +export default class DataSourcePrefetchingImageKnife implements IDataSourcePrefetching { + private dataArray: Array + private readonly requestList: HashMap = new HashMap() + private listeners: DataChangeListener[] = []; + + constructor(dataArray: Array) { + this.dataArray = dataArray; + } + public getData(index: number) { + return this.dataArray[index] + } + + public totalCount(): number { + return this.dataArray.length + } + + public addData(index: number, data: InfoItem[]): void { + this.dataArray = this.dataArray.concat(data) + this.notifyDataAdd(index) + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener) + } + } + + notifyDataAdd(index: number): void { + this.listeners.forEach((listener: DataChangeListener) => { + listener.onDataAdd(index) + }) + } + async prefetch(index: number): Promise { + let item = this.dataArray[index] + if (typeof item.albumUrl == 'string') { + // 图片预加载 + let request = ImageKnife.getInstance().preload({ + loadSrc:item.albumUrl, + onLoadListener:{ + onLoadSuccess:()=>{ + // 预加载成功,删除成功请求 + this.requestList.remove(index) + }, + onLoadFailed:()=>{ + // 移除失败请求 + this.requestList.remove(index) + } + } + }) + this.requestList.set(index,request) + } + } + // 取消请求处理 + cancel(index: number) { + if(this.requestList.hasKey(index)) { + // 返回MAP对象指定元素 + const request = this.requestList.get(index) + // 取消请求 + ImageKnife.getInstance().cancel(request) + // 移除被取消的请求对象 + this.requestList.remove(index) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/model/PageViewModel.ets b/entry/src/main/ets/pages/model/PageViewModel.ets new file mode 100644 index 0000000..237eebe --- /dev/null +++ b/entry/src/main/ets/pages/model/PageViewModel.ets @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { InfoItem } from './DataSourcePrefetching' + +export class PageViewModel { + private static dataArray: Array = [ + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/42/v3/2dSQCqERTP2TTPyssOMEbQ/zL1ebnKKQ_ilqTDcwCAkOw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/8a/v3/ZKzYV5BJTuCk5hCE0y_xNA/8JT95OQnSZSd6_xQQUONhQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/1/v3/sTXb_I7URBKjdMyLDYa19w/qpcwa_FNQmi3-EzjbGsJ8A.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e5/v3/m7wFvw_eQIuDV0Mk0IKi8g/gJU4migzTHKYk5KrgdZbBw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3f/v3/k_UWbB5_RGW7JemQZ0OQdw/_DUdmaZRQyG-Oyvkb663Bw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/39/v3/rFRN7G_VSo-p4mBjTZtkRw/gBwTI-ieSIqSsSmLNBEcgw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/04/v3/6K8BPYKVQFOr7KCuAG9nog/qKd3pZlrQy2M-feB3ycVPA.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/7d/v3/f0GQFzm1T6eduVeMUhO3Wg/-4cvzIJiRCegjIno3ofIbQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e4/v3/C0xxsSeySxW-2iYR5OEbpQ/f1GlaD3zTeKPX8Vd-M1oVQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/c2/v3/32LCyXN4TuWKWcdf9gAwWw/ej14_BCJQNCaWOKoI9aZAw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fd/v3/LyYJMdMmQNaC5GyBYEZ5Pw/uFLiovypRSagKyIS-UJPVw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/15/v3/MHM9KaWGTgubn6M8-B_6nw/1YO9JyYhTHSBWsoiqYkGZw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/4c/v3/UdYfbv1_QYqn_ulDHp89OA/VkjexMluTqGO3yt3gPK1DA.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e8/v3/N8blT_7qSK-tRtahIyov7g/M_kjGEEmSzOlTc47Zrfozg.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/28/v3/VS_h3m4YRrSgbgxnqE3vtQ/h-2Q1Qy2SSGEuXM36-Rq_w.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/2e/v3/R-BaM5ToRNGq5rwtNTcnww/Q2e01VHiR2y9KtFaZmpmNQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/88/v3/3djkAJKKTdC539XqMdstSg/wHO7DxvXQS2xbt2Y_-4BNg.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/guw4eiggR3uWjscFTxITYg/TzRB35iPTdCztrZUUaNuFg.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/93/v3/UvSh_f1LT66i0-3hvsYN_A/eYnE3Z8YT5Sk7F-vS2ZmCQ.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/5/v3/tv8Vqf9hQrKpozGeZWg2mw/VEICB-bmQYi0Iv6TGADbhw.jpg' + }, + { + albumUrl: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/4v1Ot5BRR6OFVQ9MGn9Xxg/xrPgRn0LS1ep-r7ewIuwiw.jpg' + }, + ] + static getItems() { + return PageViewModel.dataArray + } +} \ No newline at end of file diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index 6c284c7..a493443 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -42,6 +42,15 @@ ], "when": "always" } + }, + { + "name": "ohos.permission.GET_NETWORK_INFO", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "always" + } } ] } diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json index c16a7d9..055082a 100644 --- a/entry/src/main/resources/base/element/string.json +++ b/entry/src/main/resources/base/element/string.json @@ -369,20 +369,12 @@ "value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally" }, { - "name": "Image_Downsampling_Functionality", - "value": "Downscale Image effect" + "name": "Network_reload", + "value": "Network recovery reload" }, { - "name": "Sampling_pecification", - "value": "降采样规格" - }, - { - "name": "Unreal_samples", - "value": "未降采样大小" - }, - { - "name": "After_the_sampling", - "value": "降采样后大小" + "name": "preloading_prefetch", + "value": "Dynamic preloading prefetch" }, { "name": "image_format", @@ -511,6 +503,150 @@ { "name": "disk", "value": "Disk" + }, + { + "name": "Customize_RCP_network", + "value": "Customize RCP network request" + }, + { + "name": "request_concurrency", + "value": "Set request concurrency" + }, + { + "name": "test_callback", + "value": "test callback data of load pic" + }, + { + "name": "gif", + "value": "gif" + }, + { + "name": "local_pic", + "value": "local picture" + }, + { + "name": "share_pic", + "value": "share picture" + }, + { + "name": "net_load_failed", + "value": "netWork load failed" + }, + { + "name": "local_load_failed", + "value": "local load failed" + }, + { + "name": "share_load_failed", + "value": "shared load failed" + }, + { + "name": "list_pic", + "value": "load picture list" + }, + { + "name": "img_url", + "value": "url of the service setting:%s" + }, + { + "name": "img_format", + "value": "picture format:%s" + }, + { + "name": "img_master_size", + "value": "the original width and height of the picture-w:%d ,h:%d, size:%d" + }, + { + "name": "componentWH", + "value": "component width and height-w:%d ,h:%d " + }, + { + "name": "img_frame", + "value": "the number of frames of the picture:%d " + }, + { + "name": "img_content_size", + "value": "picture decoded width and height size:%s " + }, + { + "name": "err_msg", + "value": "error message:%s " + }, + { + "name": "err_phase", + "value": "error phase:%s " + }, + { + "name": "err_code", + "value": "error code:%d " + }, + { + "name": "http_code", + "value": "http code:%d " + }, + { + "name": "req_start_time", + "value": "image request start time point:%s " + }, + { + "name": "req_end_time", + "value": "the point in time at which the image request ends:%s " + }, + { + "name": "req_cancel_time", + "value": "the point at which the image request is cancelled:%s " + }, + { + "name": "memory_start_time", + "value": "start checking the memory cache point in time:%s " + }, + { + "name": "memory_end_time", + "value": "end Check the memory cache time point:%s " + }, + { + "name": "disk_start_time", + "value": "start checking the disk cache point in time:%s " + }, + { + "name": "disk_end_time", + "value": "end Check the disk cache time point:%s " + }, + { + "name": "net_start_time", + "value": "start time of the network request:%s " + }, + { + "name": "net_end_time", + "value": "end time of the network request:%s:%s " + }, + { + "name": "decode_start_time", + "value": "decoding start time point:%s " + }, + { + "name": "decode_end_time", + "value": "decoding end time point:%s " + }, + { + "name": "render_time", + "value": "render successful time:%s " + }, + { + "name": "Image_Downsampling_Functionality", + "value": "Downsampling function" + }, + { + "name": "Sampling_pecification", + "value": "Downsampling specification" + }, + { + "name": "Unreal_samples", + "value": "Unsampled size" + }, + { + "name": "After_the_sampling", + "value": "Size after downsampling" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 623e12e..199682b 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -23,9 +23,20 @@ "pages/TestSetCustomImagePage", "pages/TestErrorHolderPage", "pages/TestTaskResourcePage", - "pages/DownSamplePage", + "pages/ImageKnifeReload", + "pages/LazyForEachCount", + "pages/LazyForEachCache", + "pages/PrefetchAndCacheCount", + "pages/PrefetchAndPreload", "pages/TestCacheDataPage", "pages/TestChangeColorPage", - "pages/TestLoadCancelListenerPage" + "pages/TestLoadCancelListenerPage", + "pages/SetMaxRequestPage", + "pages/MaxRequest1", + "pages/MaxRequest2", + "pages/MaxRequest3", + "pages/TestImageKnifeCallbackPage", + "pages/TestListImageKnifeCallbackPage", + "pages/DownSamplePage" ] } \ No newline at end of file diff --git a/entry/src/main/resources/en_US/element/string.json b/entry/src/main/resources/en_US/element/string.json index 13c1fec..4d62c27 100644 --- a/entry/src/main/resources/en_US/element/string.json +++ b/entry/src/main/resources/en_US/element/string.json @@ -19,6 +19,362 @@ { "name": "app_permission_READ_IMAGEVIDEO", "value": "获取读媒体资源权限" + }, + { + "name": "Test_ImageAnimator", + "value": "Test ImageAnimator component" + }, + { + "name": "Test_multiple_images", + "value": "Test loading multiple identical images" + }, + { + "name": "Test_Task_error", + "value": "Test placeholder map Task error" + }, + { + "name": "Test_HSP", + "value": "Test HSP scene preloading" + }, + { + "name": "Test_SingleImage", + "value": "SingleImage" + }, + { + "name": "Test_custom_download", + "value": "Global custom download" + }, + { + "name": "Multiple_images", + "value": "Multiple images" + }, + { + "name": "Display_long_image", + "value": "Display long image" + }, + { + "name": "Image_scaling", + "value": "Image scaling" + }, + { + "name": "Message_list", + "value": "Message list" + }, + { + "name": "Custom_cache_key", + "value": "Custom cache key" + }, + { + "name": "Preloading_images_to_cache", + "value": "Preloading images to file cache" + }, + { + "name": "Retrieve_image_display_from_cache", + "value": "Retrieve image display from cache" + }, + { + "name": "Test_single_request_header", + "value": "Test a single request header" + }, + { + "name": "Test_write_cache_strategy", + "value": "Test write cache strategy" + }, + { + "name": "Image_Transformation", + "value": "Image Transformation" + }, + { + "name": "Different_ObjectFit", + "value": "Different ObjectFit" + }, + { + "name": "Test_image_loading_success_or_failure_events", + "value": "Test image loading success/failure events" + }, + { + "name": "Test_removing_image_cache_interface", + "value": "Test removing image cache interface" + }, + { + "name": "Test_error_image_display", + "value": "Test error image display" + }, + { + "name": "Test_media_URL", + "value": "Test media URL" + }, + { + "name": "Display_the_first_frame", + "value": "Display the first frame of the animation" + }, + { + "name": "Display_the_last_frame", + "value": "Display the last frame of the animation" + }, + { + "name": "Play", + "value": "Play" + }, + { + "name": "Pause", + "value": "Pause" + }, + { + "name": "Stop", + "value": "Stop" + }, + { + "name": "Infinite_loop", + "value": "Infinite loop" + }, + { + "name": "Play_once", + "value": "Play once" + }, + { + "name": "Play_twice", + "value": "Play twice" + }, + { + "name": "Local_SVG", + "value": "Local SVG image" + }, + { + "name": "Under_context_file", + "value": "Files under context file" + }, + { + "name": "Network_images", + "value": "Network images" + }, + { + "name": "Custom_network_download", + "value": "Custom network download" + }, + { + "name": "PixelMap_loads_images", + "value": "PixelMap loads images" + }, + { + "name": "Enlarge", + "value": "Enlarge" + }, + { + "name": "Reduce", + "value": "Reduce" + }, + { + "name": "Click_on_add", + "value": "Click on the size to add 50" + }, + { + "name": "Click_on_reduce", + "value": "Click to reduce size by 50" + }, + { + "name": "The_key_fixed_1", + "value": "The key is fixed at 1" + }, + { + "name": "The_key_changes_timestamp", + "value": "Key changes every time: timestamp" + }, + { + "name": "Load", + "value": "Load" + }, + { + "name": "Preloading_images_to_file_cache_using_URL", + "value": "Preloading images to file cache using URL" + }, + { + "name": "Preloading_images_to_file_cache_using_option", + "value": "Preloading images to file cache using option" + }, + { + "name": "Load_image_offline_after_preloading", + "value": "Load image (can be loaded offline after preloading)" + }, + { + "name": "Preloading_GIF", + "value": "Preloading GIF" + }, + { + "name": "Retrieve_GIF_from_memory", + "value": "Retrieve GIF from memory cache" + }, + { + "name": "Retrieve_GIF_from_disk", + "value": "Retrieve GIF from disk cache" + }, + { + "name": "Preloading_static_images", + "value": "Preloading static images" + }, + { + "name": "Retrieve_images_from_memory", + "value": "Retrieve images from memory cache" + }, + { + "name": "Retrieve_images_from_disk", + "value": "Retrieve images from memory disk" + }, + { + "name": "Write_memory_and_file", + "value": "Write to memory and file cache" + }, + { + "name": "Write_memory", + "value": "Write to memory cache" + }, + { + "name": "Write_file", + "value": "Write to file cache" + }, + { + "name": "Main_image_Fill", + "value": "Main image Fill Stretch Fill" + }, + { + "name": "Maintain_proportion_filling", + "value": "Maintain proportion filling in the placeholder map 'Include'" + }, + { + "name": "Error_graph_None", + "value": "Error graph None remains unchanged" + }, + { + "name": "Test_failure_success", + "value": "Test failure/success" + }, + { + "name": "Custom_download_failed", + "value": "Custom download failed" + }, + { + "name": "Retrieve_media_gallery", + "value": "Retrieve the URI of the media gallery and display it using ImageKnife" + }, + { + "name": "Click_load_Uri", + "value": "Click to load Uri and display" + }, + { + "name": "Delete_all_caches", + "value": "Delete all caches" + }, + { + "name": "Delete_all_memory_caches", + "value": "Delete all memory caches" + }, + { + "name": "Delete_all_file_caches", + "value": "Delete all file caches" + }, + { + "name": "Delete_all_custom_memory_caches", + "value": "Delete all custom memory caches" + }, + { + "name": "Delete_all_custom_file_caches", + "value": "Delete all custom file caches" + }, + { + "name": "Blur_effect", + "value": "Blur effect" + }, + { + "name": "Highlighting_effect", + "value": "Highlighting effect" + }, + { + "name": "Ashing_effect", + "value": "Ashing effect" + }, + { + "name": "Inverse_effect", + "value": "Inverse effect" + }, + { + "name": "Animation_filter_effect", + "value": "Animation filter effect" + }, + { + "name": "Crop_circular_effect", + "value": "Crop circular effect" + }, + { + "name": "Crop_circular_with_border_effect", + "value": "Crop circular with border effect" + }, + { + "name": "Contrast_effect", + "value": "Contrast effect" + }, + { + "name": "Black_ink_filtering_effect", + "value": "Black ink filtering effect" + }, + { + "name": "Rotate", + "value": "Rotate" + }, + { + "name": "Corners", + "value": "Corners" + }, + { + "name": "Kuwahara_Filter_effect", + "value": "Kuwahara filter effect" + }, + { + "name": "Pixelated_Filter_effect", + "value": "Pixelated filtering effect" + }, + { + "name": "Sketch_Filter_effect", + "value": "Sketch Filter effect" + }, + { + "name": "Distortion_Filter_effect", + "value": "Distortion Filter effect" + }, + { + "name": "Decorative_Filter_effect", + "value": "Decorative Filter effect" + }, + { + "name": "Square_cutting_effect", + "value": "Square cutting effect" + }, + { + "name": "Top_cutting_effect", + "value": "Top cutting effect" + }, + { + "name": "Middle_cutting_effect", + "value": "Middle cutting effect" + }, + { + "name": "Bottom_cutting_effect", + "value": "Bottom cutting effect" + }, + { + "name": "Mask_effect", + "value": "Mask effect" + }, + { + "name": "TIPS", + "value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally" + }, + { + "name": "Network_reload", + "value": "Network recovery reload" + }, + { + "name": "preloading_prefetch", + "value": "Dynamic preloading prefetch" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/zh_CN/element/string.json b/entry/src/main/resources/zh_CN/element/string.json index 5e5e284..c6ea1fc 100644 --- a/entry/src/main/resources/zh_CN/element/string.json +++ b/entry/src/main/resources/zh_CN/element/string.json @@ -365,20 +365,12 @@ "value": "测试失败场景请先关闭网络,并保证本地没有此网络图片的缓存" }, { - "name": "Image_Downsampling_Functionality", - "value": "降采样功能" + "name": "Network_reload", + "value": "网络恢复reload" }, { - "name": "Sampling_pecification", - "value": "降采样规格" - }, - { - "name": "Unreal_samples", - "value": "未降采样大小" - }, - { - "name": "After_the_sampling", - "value": "降采样后大小" + "name": "preloading_prefetch", + "value": "动态预加载prefetch" }, { "name": "image_format", @@ -507,6 +499,150 @@ { "name": "disk", "value": "磁盘" + }, + { + "name": "Customize_RCP_network", + "value": "自定义rcp网络请求" + }, + { + "name": "request_concurrency", + "value": "设置请求并发度" + }, + { + "name": "test_callback", + "value": "测试图片加载回调数据" + }, + { + "name": "gif", + "value": "gif" + }, + { + "name": "local_pic", + "value": "本地图片" + }, + { + "name": "share_pic", + "value": "共享图片" + }, + { + "name": "net_load_failed", + "value": "网络加载失败" + }, + { + "name": "local_load_failed", + "value": "本地加载失败" + }, + { + "name": "share_load_failed", + "value": "共享图片加载失败" + }, + { + "name": "list_pic", + "value": "加载图片列表" + }, + { + "name": "img_url", + "value": "业务设置的url:%s" + }, + { + "name": "img_format", + "value": "图片的格式:%s" + }, + { + "name": "img_master_size", + "value": "图片的原始宽高大小-宽:%d ,高:%d, 大小:%d" + }, + { + "name": "componentWH", + "value": "component的宽高-宽:%d ,高:%d " + }, + { + "name": "img_frame", + "value": "图片的帧数:%d " + }, + { + "name": "img_content_size", + "value": "图片解码后宽高大小:%s " + }, + { + "name": "err_msg", + "value": "错误信息:%s " + }, + { + "name": "err_phase", + "value": "发生错误阶段:%s " + }, + { + "name": "err_code", + "value": "错误code:%d " + }, + { + "name": "http_code", + "value": "网络请求code:%d " + }, + { + "name": "req_start_time", + "value": "图片的请求开始时间点:%s " + }, + { + "name": "req_end_time", + "value": "图片请求结束的时间点:%s " + }, + { + "name": "req_cancel_time", + "value": "图片请求取消的时间点:%s " + }, + { + "name": "memory_start_time", + "value": "开始检查内存缓存时间点:%s " + }, + { + "name": "memory_end_time", + "value": "结束检查内存缓存时间点:%s " + }, + { + "name": "disk_start_time", + "value": "开始检查磁盘缓存时间点:%s " + }, + { + "name": "disk_end_time", + "value": "结束检查磁盘缓存时间点:%s " + }, + { + "name": "net_start_time", + "value": "网络请求开始时间点:%s " + }, + { + "name": "net_end_time", + "value": "网络请求结束时间点:%s " + }, + { + "name": "decode_start_time", + "value": "解码开始时间点:%s " + }, + { + "name": "decode_end_time", + "value": "解码结束时间点:%s " + }, + { + "name": "render_time", + "value": "渲染成功的时间:%s " + }, + { + "name": "Image_Downsampling_Functionality", + "value": "降采样功能" + }, + { + "name": "Sampling_pecification", + "value": "降采样规格" + }, + { + "name": "Unreal_samples", + "value": "未降采样大小" + }, + { + "name": "After_the_sampling", + "value": "降采样后大小" } ] } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/DefaultJobQueueTest.test.ets b/entry/src/ohosTest/ets/test/DefaultJobQueueTest.test.ets index 71dfa05..adad3e5 100644 --- a/entry/src/ohosTest/ets/test/DefaultJobQueueTest.test.ets +++ b/entry/src/ohosTest/ets/test/DefaultJobQueueTest.test.ets @@ -55,12 +55,12 @@ export default function DefaultJobQueueTest() { expect(job.getQueueLength()).assertEqual(7) expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("high1") - expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium4") - expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium3") - expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium2") expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium1") - expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low2") + expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium2") + expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium3") + expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium4") expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low1") + expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low2") expect(job.pop()).assertEqual(undefined) expect(job.getQueueLength()).assertEqual(0) diff --git a/entry/src/ohosTest/ets/test/imageknifeOption.test.ets b/entry/src/ohosTest/ets/test/ImageknifeOption.test.ets similarity index 100% rename from entry/src/ohosTest/ets/test/imageknifeOption.test.ets rename to entry/src/ohosTest/ets/test/ImageknifeOption.test.ets diff --git a/entry/src/ohosTest/ets/test/List.test.ets b/entry/src/ohosTest/ets/test/List.test.ets index 9b109cc..106d177 100644 --- a/entry/src/ohosTest/ets/test/List.test.ets +++ b/entry/src/ohosTest/ets/test/List.test.ets @@ -14,12 +14,13 @@ */ import DefaultJobQueueTest from './DefaultJobQueueTest.test'; import FileLruCacheTest from './FileLruCache.test'; -import ImageKnifeOptionTest from './ImageKnifeOption.test'; +import ImageKnifeOptionTest from './ImageknifeOption.test'; import MemoryLruCacheTest from './MemoryLruCache.test'; import ImageKnifeTest from './ImageKnife.test'; import Transform from './transform.test'; -import SamplingTest from './SamplingTest.test'; import imageFormatAndSize from './imageFormatAndSize.test' +import loadCallBackData from './loadCallBackData.test' +import SamplingTest from './SamplingTest.test'; export default function testsuite() { MemoryLruCacheTest(); @@ -30,4 +31,5 @@ export default function testsuite() { Transform(); SamplingTest() imageFormatAndSize(); + loadCallBackData(); } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/SamplingTest.test.ets b/entry/src/ohosTest/ets/test/SamplingTest.test.ets index 074057d..c11562d 100644 --- a/entry/src/ohosTest/ets/test/SamplingTest.test.ets +++ b/entry/src/ohosTest/ets/test/SamplingTest.test.ets @@ -15,7 +15,7 @@ import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' import { image } from '@kit.ImageKit' import { BusinessError } from '@kit.BasicServicesKit' -import { calculateScaleType, Downsampler } from '@ohos/imageknife/src/main/ets/downsampling/Downsampler' +import { Downsampler } from '@ohos/imageknife/src/main/ets/downsampling/Downsampler' import { DownsampleStrategy } from '@ohos/imageknife' export default function SamplingTest() { @@ -39,41 +39,48 @@ export default function SamplingTest() { // Presets a clear action, which is performed after all test cases of the test suite end. // This API supports only one parameter: clear action function. }) - it('NONE', 0, () => { - let reqSize: calculateScaleType = - new Downsampler().calculateScaling('jpg', 1024, 1024, 200, - 200, DownsampleStrategy.NONE,) - let req = (reqSize.targetWidth == 1024 && reqSize.targetHeight == 1024) - expect(req).assertEqual(true); - }) - it('AT_MOST', 1, () => { - let reqSize: calculateScaleType = + it('AT_MOST', 0, () => { + let reqSize: Size = new Downsampler().calculateScaling('jpg', 1024, 1024, 200, 200, DownsampleStrategy.AT_MOST) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) + let req = (reqSize.width < 1024 && reqSize.height < 1024) expect(req).assertEqual(true); }) - it('FIT_CENTER', 2, () => { - let reqSize: calculateScaleType = + it('FIT_CENTER_MEMORY', 1, () => { + let reqSize: Size = new Downsampler().calculateScaling('jpg', 1024, 1024, 200, 200, DownsampleStrategy.FIT_CENTER_MEMORY) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) + let req = (reqSize.width < 1024 && reqSize.height < 1024) expect(req).assertEqual(true); }) - it('CENTER_OUTSIDE', 3, () => { - let reqSize: calculateScaleType = + it('FIT_CENTER_QUALITY', 2, () => { + let reqSize: Size = + new Downsampler().calculateScaling('jpg', 1024, 1024, 200, + 200, DownsampleStrategy.FIT_CENTER_QUALITY) + let req = (reqSize.width < 1024 && reqSize.height < 1024) + expect(req).assertEqual(true); + }) + it('CENTER_OUTSIDE_MEMORY', 3, () => { + let reqSize: Size = new Downsampler().calculateScaling('jpg', 1024, 1024, 200, 200, DownsampleStrategy.CENTER_OUTSIDE_MEMORY) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) + let req = (reqSize.width < 1024 && reqSize.height < 1024) expect(req).assertEqual(true); }) - it('AT_LEAST', 4, () => { - let reqSize: calculateScaleType = + it('CENTER_OUTSIDE_QUALITY', 4, () => { + let reqSize: Size = + new Downsampler().calculateScaling('jpg', 1024, 1024, 200, + 200, DownsampleStrategy.CENTER_OUTSIDE_QUALITY) + let req = (reqSize.width < 1024 && reqSize.height < 1024) + expect(req).assertEqual(true); + }) + it('AT_LEAST', 5, () => { + let reqSize: Size = new Downsampler().calculateScaling('jpg', 1024, 1024, 200, 200, DownsampleStrategy.AT_LEAST) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) + let req = (reqSize.width < 1024 && reqSize.height < 1024) expect(req).assertEqual(true); }) }) -} +} \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/SendableData.test.ets b/entry/src/ohosTest/ets/test/SendableData.test.ets deleted file mode 100644 index e98f65d..0000000 --- a/entry/src/ohosTest/ets/test/SendableData.test.ets +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' -import { SendableData } from '@ohos/imageknife/src/main/ets/components/imageknife/SendableData' - -export default function SendableDataTest() { - describe('SendableDataTest', ()=> { - // Defines a test suite. Two parameters are supported: test suite name and test suite function. - beforeAll( ()=> { - // Presets an action, which is performed only once before all test cases of the test suite start. - // This API supports only one parameter: preset action function. - }) - beforeEach( ()=> { - // Presets an action, which is performed before each unit test case starts. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: preset action function. - }) - afterEach( ()=> { - // Presets a clear action, which is performed after each unit test case ends. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: clear action function. - }) - afterAll( ()=> { - // Presets a clear action, which is performed after all test cases of the test suite end. - // This API supports only one parameter: clear action function. - }) - it('TestPlaceHolderCacheKey', 0, () => { - let value: string = "placeholderRegisterCacheKey"; - let data: SendableData = new SendableData(); - data.setPlaceHolderRegisterCacheKey(value); - expect(data.getPlaceHolderRegisterCacheKey()).assertEqual(value); - }) - it('TestPlaceHolderMemoryCacheKey', 1, () => { - let value: string = "placeholderRegisterMemoryCacheKey"; - let data: SendableData = new SendableData(); - data.setPlaceHolderRegisterMemoryCacheKey(value); - expect(data.getPlaceHolderRegisterMemoryCacheKey()).assertEqual(value); - }) - }) -} \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/customdatafetchclient.test.ets b/entry/src/ohosTest/ets/test/customdatafetchclient.test.ets deleted file mode 100644 index 38109e7..0000000 --- a/entry/src/ohosTest/ets/test/customdatafetchclient.test.ets +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' -import { DownloadClient } from '@ohos/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient'; -import common from '@ohos.app.ability.common'; -import { GlobalContext } from '../testability/GlobalContext'; -import { CustomDataFetchClient, DataFetchResult, ImageKnifeGlobal, RequestOption } from '@ohos/imageknife'; - -const BASE_COUNT: number = 2000; - -export default function CustomDataFetchClientTest() { - describe('CustomDataFetchClientTest', () => { - // Defines a test suite. Two parameters are supported: test suite name and test suite function. - beforeAll(() => { - // Presets an action, which is performed only once before all test cases of the test suite start. - // This API supports only one parameter: preset action function. - }) - beforeEach(() => { - // Presets an action, which is performed before each unit test case starts. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: preset action function. - }) - afterEach(() => { - // Presets a clear action, which is performed after each unit test case ends. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: clear action function. - }) - afterAll(() => { - // Presets a clear action, which is performed after all test cases of the test suite end. - // This API supports only one parameter: clear action function. - }) - it('TestIsLocalLoadSrc', 0, () => { - let path = 'invalid path'; - let client = new DownloadClient() - expect(client.isLocalLoadSrc(undefined, path)).assertFalse(); - let context: object | undefined = GlobalContext.getInstance().getObject("hapContext"); - if (context != undefined) { - let loadSrc1 = (context as common.UIAbilityContext).filesDir + 'a.jpg'; - let loadSrc2 = (context as common.UIAbilityContext).cacheDir + 'b.jpg'; - expect(client.isLocalLoadSrc(context, loadSrc1)).assertTrue(); - expect(client.isLocalLoadSrc(context, loadSrc2)).assertTrue(); - } - }) - it('TestLoadData', 1, async () => { - let client = new CustomDataFetchClient(); - let request = new RequestOption(); - request.loadSrc = $r('app.media.icon'); - let error = (await client.loadData(request) as DataFetchResult).error as String; - expect(error).assertEqual('CustomDataFetchClient request or loadSrc error.'); - }) - it('TestLoadData_customGetImage', 2, async () => { - let client = new CustomDataFetchClient(); - let request = new RequestOption(); - request.loadSrc = 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg'; - request.customGetImage = (context: Context, src: string) => { - // 这里是模拟的customGetImage逻辑 - return Promise.resolve(new DataFetchResult()); - } - console.log('LXH', 'TestLoadData 2 --1 customGetImage is undefined ?' + (request.customGetImage == undefined)); - let context: object | undefined = GlobalContext.getInstance().getObject("hapContext"); - let result = await client.loadData(request); - if (context != undefined) { - console.log('LXH', 'TestLoadData 2 --2'); - expect(typeof result) - .assertEqual(typeof (await request?.customGetImage(context as common.UIAbilityContext, request.loadSrc))); - } - }) - it('TestLoadData_combineArrayBuffers', 3, () => { - // 创建几个ArrayBuffer作为测试数据 - const arrayBuffer1 = new ArrayBuffer(4); - const uint8Array1 = new Uint8Array(arrayBuffer1); - uint8Array1[0] = 1; - uint8Array1[1] = 2; - uint8Array1[2] = 3; - uint8Array1[3] = 4; - - const arrayBuffer2 = new ArrayBuffer(2); - const uint8Array2 = new Uint8Array(arrayBuffer2); - uint8Array2[0] = 5; - uint8Array2[1] = 6; - let client = new CustomDataFetchClient(); - const combinedArrayBuffer = client.combineArrayBuffers([arrayBuffer1, arrayBuffer2]); - expect(combinedArrayBuffer.byteLength).assertEqual(6); - const combinedUint8Array = new Uint8Array(combinedArrayBuffer); - for (let i = 0; i < 4; i++) { - expect(combinedUint8Array[i]).assertEqual(uint8Array1[i]); - } - for (let i = 0; i < 2; i++) { - expect(combinedUint8Array[i + 4]).assertEqual(uint8Array2[i]); - } - }); - }) -} - diff --git a/entry/src/ohosTest/ets/test/imageFormatAndSize.test.ets b/entry/src/ohosTest/ets/test/imageFormatAndSize.test.ets index fea2a53..9b7b49e 100644 --- a/entry/src/ohosTest/ets/test/imageFormatAndSize.test.ets +++ b/entry/src/ohosTest/ets/test/imageFormatAndSize.test.ets @@ -49,9 +49,9 @@ export default function imageFormatAndSize() { let imageFormat: string = ""; let url: string = "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg" - let imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + let imageKnifeOption: ImageKnifeOption = { loadSrc: url, - }) + } await new Promise((resolve, reject) => { imageKnifeOption.onLoadListener = { onLoadSuccess: (data, imageknifeData) => { diff --git a/entry/src/ohosTest/ets/test/loadCallBackData.test.ets b/entry/src/ohosTest/ets/test/loadCallBackData.test.ets new file mode 100644 index 0000000..256159b --- /dev/null +++ b/entry/src/ohosTest/ets/test/loadCallBackData.test.ets @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import { + ImageKnifeOption, + ImageKnife, + ImageKnifeRequest, + ImageKnifeRequestSource, + CacheStrategy +} from "@ohos/imageknife" +import { common } from '@kit.AbilityKit'; + +export default function loadCallBackData() { + describe('loadCallBackData', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('startAndSuccess-CallBack', 0, async () => { + let startCallBack: ESObject = undefined; + let successCallBack: ESObject = undefined; + let url: string = + "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg" + let imageKnifeOption: ImageKnifeOption = { + loadSrc: url, + } + await new Promise((resolve, reject) => { + imageKnifeOption.onLoadListener = { + onLoadStart: (data) => { + startCallBack = data?.getImageKnifeData(); + }, + onLoadSuccess: (data, imageknifeData,req) => { + successCallBack = req?.getImageKnifeData(); + resolve("") + }, + onLoadFailed(err) { + reject(err) + } + } + let request = new ImageKnifeRequest( + imageKnifeOption, + imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext() as common.UIAbilityContext, + 0, + 0, + 0, + { + showPixelMap(version: number, pixelMap: PixelMap | string) { + } + } + ) + ImageKnife.getInstance().execute(request); + }) + expect(startCallBack != undefined).assertTrue(); + expect(successCallBack != undefined).assertTrue(); + }); + it('failed-CallBack', 0, async () => { + let failedCallBack: ESObject = undefined; + let url: string = + "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/163/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg" + let imageKnifeOption: ImageKnifeOption = { + loadSrc: url, + } + await new Promise((resolve, reject) => { + imageKnifeOption.onLoadListener = { + onLoadStart: (data) => { + }, + onLoadSuccess: (data, imageknifeData) => { + }, + onLoadFailed(res,req) { + failedCallBack = req?.getImageKnifeData(); + resolve(res) + } + } + let request = new ImageKnifeRequest( + imageKnifeOption, + imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext() as common.UIAbilityContext, + 0, + 0, + 0, + { + showPixelMap(version: number, pixelMap: PixelMap | string) { + } + } + ) + ImageKnife.getInstance().execute(request); + }) + expect(failedCallBack != undefined).assertTrue(); + }); + }); +} \ No newline at end of file diff --git a/library/index.ets b/library/index.ets index 058e860..6f44833 100644 --- a/library/index.ets +++ b/library/index.ets @@ -30,6 +30,8 @@ export { IEngineKey } from './src/main/ets/key/IEngineKey' export { ImageKnifeData , CacheStrategy , ImageKnifeRequestSource} from "./src/main/ets/model/ImageKnifeData" +export { DownsampleStrategy } from './src/main/ets/downsampling/DownsampleStartegy' + export { PixelMapTransformation } from './src/main/ets/transform/PixelMapTransformation' export { MultiTransTransformation } from './src/main/ets/transform/MultiTransTransformation' @@ -67,5 +69,3 @@ export { CropTransformation } from './src/main/ets/transform/CropTransformation' export { MaskTransformation } from './src/main/ets/transform/MaskTransformation' export { SepiaTransformation } from './src/main/ets/transform/SepiaTransformation' - -export { DownsampleStrategy } from './src/main/ets/downsampling/DownsampleStartegy' \ No newline at end of file diff --git a/library/oh-package-lock.json5 b/library/oh-package-lock.json5 index 3245bae..e2f23b9 100644 --- a/library/oh-package-lock.json5 +++ b/library/oh-package-lock.json5 @@ -1,6 +1,19 @@ { + "meta": { + "stableOrder": false + }, "lockfileVersion": 3, "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", - "specifiers": {}, - "packages": {} + "specifiers": { + "@ohos/gpu_transform@^1.0.2": "@ohos/gpu_transform@1.0.4" + }, + "packages": { + "@ohos/gpu_transform@1.0.4": { + "name": "@ohos/gpu_transform", + "version": "1.0.4", + "integrity": "sha512-PrKlOK66kzObw/ANIzt55YMrOLLmtrhmAZIE2c/60GBoTl7+NLxONeHA2NsDZuiW+A0KnD4QylDYWH4/yo8T0w==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/gpu_transform/-/gpu_transform-1.0.4.har", + "registryType": "ohpm" + } + } } \ No newline at end of file diff --git a/library/oh-package.json5 b/library/oh-package.json5 index ca33846..9fd6357 100644 --- a/library/oh-package.json5 +++ b/library/oh-package.json5 @@ -14,7 +14,7 @@ "main": "index.ets", "repository": "https://gitee.com/openharmony-tpc/ImageKnife", "type": "module", - "version": "3.1.1-rc.0", + "version": "3.2.0-rc.2", "dependencies": { "@ohos/gpu_transform": "^1.0.2" }, diff --git a/library/src/main/ets/ImageKnife.ets b/library/src/main/ets/ImageKnife.ets index 79c9fe6..50a4ef4 100644 --- a/library/src/main/ets/ImageKnife.ets +++ b/library/src/main/ets/ImageKnife.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeRequest } from './model/ImageKnifeRequest'; +import { ImageKnifeRequest, ImageKnifeRequestState } from './model/ImageKnifeRequest'; import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData'; import { MemoryLruCache } from './cache/MemoryLruCache'; import { IMemoryCache } from './cache/IMemoryCache' @@ -38,7 +38,7 @@ export class ImageKnife { private _isRequestInSubThread: boolean = true; //定义全局网络请求header map headerMap: Map = new Map(); - customGetImage: ((context: Context, src: string | PixelMap | Resource) => Promise) | undefined = undefined + customGetImage: ((context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise) | undefined = undefined public static getInstance(): ImageKnife { if (!ImageKnife.instance) { ImageKnife.instance = new ImageKnife(); @@ -80,7 +80,15 @@ export class ImageKnife { public isFileCacheInit(): boolean { return this.fileCache === undefined ? false : this.fileCache.isFileCacheInit() } - + /** + * 重新加载 + */ + reload(request: ImageKnifeRequest) { + if (request.requestState == ImageKnifeRequestState.ERROR) { + request.requestState = ImageKnifeRequestState.PROGRESS + ImageKnife.getInstance().execute(request) + } + } /** * 全局添加单个请求头header * @param key 请求头属性 @@ -137,8 +145,39 @@ export class ImageKnife { let key = this.getEngineKeyImpl().generateMemoryKey(imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC, imageKnifeOption); this.memoryCache.remove(key); } - - + /** + * 预加载 + * @param loadSrc 图片地址url + * @returns 图片请求request + */ + preload(loadSrc:string | ImageKnifeOption):ImageKnifeRequest{ + let imageKnifeOption = new ImageKnifeOption() + if (typeof loadSrc == 'string') { + imageKnifeOption.loadSrc = loadSrc + } else { + imageKnifeOption = loadSrc; + } + let request = new ImageKnifeRequest( + imageKnifeOption, + imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext(this) as common.UIAbilityContext, + 0, + 0, + 0, + { + showPixelMap(version: number, pixelMap: PixelMap | string) { + } + } + ) + this.execute(request) + return request + } + /** + * 取消图片请求 + * @param request 图片请求request + */ + cancel(request:ImageKnifeRequest) { + request.requestState = ImageKnifeRequestState.DESTROY + } /** * 预加载图片到文件缓存 * @param loadSrc 图片地址url @@ -147,15 +186,15 @@ export class ImageKnife { preLoadCache(loadSrc: string | ImageKnifeOption): Promise { return new Promise((resolve, reject) => { let imageKnifeOption = new ImageKnifeOption() - if (typeof loadSrc == "string") { + if (typeof loadSrc == 'string') { imageKnifeOption.loadSrc = loadSrc } else { imageKnifeOption = loadSrc; } - LogUtil.log("ImageKnife_DataTime_preLoadCache-imageKnifeOption:"+loadSrc) + LogUtil.log('ImageKnife_DataTime_preLoadCache-imageKnifeOption:'+loadSrc) let fileKey = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature) let cachePath = ImageKnife.getInstance().getFileCache().getFileToPath(fileKey) - if (cachePath == null || cachePath == "" || cachePath == undefined) { + if (cachePath == null || cachePath == '' || cachePath == undefined) { imageKnifeOption.onLoadListener = { onLoadSuccess(){ resolve(ImageKnife.getInstance().getFileCache().getFileToPath(fileKey)) @@ -191,10 +230,10 @@ export class ImageKnife { */ getCacheImage(loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string): Promise { - let option: ImageKnifeOption = new ImageKnifeOption({ + let option: ImageKnifeOption = { loadSrc: loadSrc, signature:signature - }) + } let engineKeyImpl: IEngineKey = this.getEngineKeyImpl(); return new Promise((resolve, reject) => { @@ -218,7 +257,7 @@ export class ImageKnife { */ putCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) { let memoryKey = this.getEngineKeyImpl() - .generateMemoryKey(url, ImageKnifeRequestSource.SRC, new ImageKnifeOption({ loadSrc: url, signature: signature })); + .generateMemoryKey(url, ImageKnifeRequestSource.SRC, { loadSrc: url, signature: signature }); let fileKey = this.getEngineKeyImpl().generateFileKey(url, signature); let imageKnifeData: ImageKnifeData = { source: pixelMap, imageWidth: 0, imageHeight: 0 }; switch (cacheType) { @@ -252,9 +291,9 @@ export class ImageKnife { if (url instanceof ImageKnifeOption) { imageKnifeOption = url; } else { - imageKnifeOption = new ImageKnifeOption({ + imageKnifeOption = { loadSrc: url - }); + }; } let key = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature); if (this.fileCache !== undefined) { @@ -278,14 +317,14 @@ export class ImageKnife { } loadFromMemoryCache(key: string): ImageKnifeData | undefined { - if (key !== "") { + if (key !== '') { return this.memoryCache.get(key) } return undefined } saveMemoryCache(key: string, data: ImageKnifeData): void { - if (key !== "") { + if (key !== '') { this.memoryCache.put(key, data) } } @@ -307,7 +346,7 @@ export class ImageKnife { * @param cacheType * @returns */ - getCacheUpperLimit(cacheType?: CacheStrategy): number | undefined { + getCacheLimitSize(cacheType?: CacheStrategy): number | undefined { if (cacheType == undefined || cacheType == CacheStrategy.Default) { cacheType = CacheStrategy.Memory; } @@ -317,7 +356,7 @@ export class ImageKnife { if (this.isFileCacheInit()) { return this.fileCache?.maxMemory; } else { - throw new Error("the disk cache not init"); + throw new Error('the disk cache not init'); } } } @@ -327,7 +366,7 @@ export class ImageKnife { * @param cacheType * @returns */ - getCurrentPicturesNum(cacheType: CacheStrategy): number | undefined { + getCurrentCacheNum(cacheType: CacheStrategy): number | undefined { if (cacheType == undefined || cacheType == CacheStrategy.Default) { cacheType = CacheStrategy.Memory; } @@ -337,7 +376,7 @@ export class ImageKnife { if (this.isFileCacheInit()) { return this.fileCache?.size(); } else { - throw new Error("the disk cache not init"); + throw new Error('the disk cache not init'); } } } @@ -357,12 +396,11 @@ export class ImageKnife { if (this.isFileCacheInit()) { return this.fileCache?.currentMemory; } else { - throw new Error("the disk cache not init"); + throw new Error('the disk cache not init'); } } } - private pixelMapToArrayBuffer(pixelMap: PixelMap): ArrayBuffer { let imageInfo = pixelMap.getImageInfoSync(); let readBuffer: ArrayBuffer = new ArrayBuffer(imageInfo.size.height * imageInfo.size.width * 4); @@ -386,7 +424,7 @@ export class ImageKnife { if (typeValue === 'gif' || typeValue === 'webp') { let base64Help = new util.Base64Helper() - let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(buffer)) + let base64str = 'data:image/' + typeValue + ';base64,' + base64Help.encodeToStringSync(new Uint8Array(buffer)) onComplete({ source: base64str, imageWidth: 0, @@ -425,12 +463,12 @@ export class ImageKnife { } async execute(request: ImageKnifeRequest,isAnimator?: boolean): Promise { - LogUtil.log("ImageKnife_DataTime_execute.start:"+request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_execute.start:'+request.imageKnifeOption.loadSrc) if (this.headerMap.size > 0) { request.addHeaderMap(this.headerMap) } this.dispatcher.enqueue(request,isAnimator) - LogUtil.log("ImageKnife_DataTime_execute.end:"+request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_execute.end:'+request.imageKnifeOption.loadSrc) } setEngineKeyImpl(impl: IEngineKey): void { @@ -444,10 +482,10 @@ export class ImageKnife { * 全局设置自定义下载 * @param customGetImage 自定义请求函数 */ - setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise) { + setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise) { this.customGetImage = customGetImage } - getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource) => Promise){ + getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise){ return this.customGetImage } } \ No newline at end of file diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index e2e1466..c95f54d 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -19,10 +19,10 @@ import List from '@ohos.util.List'; import LightWeightMap from '@ohos.util.LightWeightMap'; import { LogUtil } from './utils/LogUtil'; import { ImageKnife } from './ImageKnife'; -import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData'; +import { ImageKnifeData, CacheStrategy, TimeInfo, ErrorInfo } from './model/ImageKnifeData'; import image from '@ohos.multimedia.image'; import emitter from '@ohos.events.emitter'; -import { Constants } from './utils/Constants'; +import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants'; import taskpool from '@ohos.taskpool'; import { FileTypeUtil } from './utils/FileTypeUtil'; import { IEngineKey } from './key/IEngineKey'; @@ -49,8 +49,9 @@ export class ImageKnifeDispatcher { private engineKey: IEngineKey = new DefaultEngineKey(); showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean { - LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc + "requestSource=" + requestSource + " isAnimator=" + isAnimator) + LogUtil.log('ImageKnife_DataTime_showFromMemomry.start:' + request.imageKnifeOption.loadSrc + 'requestSource=' + requestSource + ' isAnimator=' + isAnimator) let memoryCache: ImageKnifeData | undefined; + let memoryCheckStartTime = Date.now(); if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') { memoryCache = { source: request.imageKnifeOption.loadSrc as image.PixelMap, @@ -62,38 +63,100 @@ export class ImageKnifeDispatcher { .loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator)); } + //记录ImageKnifeRequestSource.SRC 开始内存检查的时间点 + if (requestSource == ImageKnifeRequestSource.SRC && request.getImageKnifeData()) { + let timeInfo = request.getImageKnifeData()?.timeInfo + if (timeInfo) { + timeInfo.memoryCheckStartTime = memoryCheckStartTime; + timeInfo.memoryCheckEndTime = Date.now(); + //设置请求结束的时间点 + if (memoryCache !== undefined) { + timeInfo.requestEndTime = Date.now(); + } + } + } + if (memoryCache !== undefined) { // 画主图 if (request.requestState === ImageKnifeRequestState.PROGRESS) { // 回调请求开始 if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { - request.imageKnifeOption.onLoadListener.onLoadStart() - LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc) + request.imageKnifeOption.onLoadListener.onLoadStart(request) + LogUtil.log('ImageKnife_DataTime_MemoryCache_onLoadStart:' + request.imageKnifeOption.loadSrc) } - LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc) - request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, requestSource,memoryCache.imageAnimator) - LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.end:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_MemoryCache_showPixelMap.start:' + request.imageKnifeOption.loadSrc) + request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, + { width: memoryCache.imageWidth, height: memoryCache.imageHeight }, requestSource, memoryCache.imageAnimator) + LogUtil.log('ImageKnife_DataTime_MemoryCache_showPixelMap.end:' + request.imageKnifeOption.loadSrc) if (requestSource == ImageKnifeRequestSource.SRC) { request.requestState = ImageKnifeRequestState.COMPLETE // 回调请求开结束 if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) { - request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source,memoryCache) - LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc) + this.copyMemoryCacheInfo(memoryCache, request.getImageKnifeData()); + request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source, memoryCache, request) + LogUtil.log('ImageKnife_DataTime_MemoryCache_onLoadSuccess:' + request.imageKnifeOption.loadSrc) } } else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) { request.requestState = ImageKnifeRequestState.ERROR } } - LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_hasmemory:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_showFromMemomry.end_hasmemory:' + request.imageKnifeOption.loadSrc) return true } - LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_nomemory:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_showFromMemomry.end_nomemory:' + request.imageKnifeOption.loadSrc) return false } + private copyMemoryCacheInfo(memoryCache: ImageKnifeData | undefined, target: ImageKnifeData | undefined) { + if (!memoryCache || !target) { + return; + } + target.source = memoryCache.source; + target.imageWidth = memoryCache.imageWidth; + target.imageHeight = memoryCache.imageHeight; + target.type = memoryCache.type; + target.imageAnimator = memoryCache.imageAnimator; + } + + private assembleImageKnifeData(beforeCallData: ImageKnifeData | undefined, afterCallData: ImageKnifeData | undefined, req: ImageKnifeRequest) { + if (!beforeCallData || !afterCallData || !req) { + return; + } + //设置图片开始加载时间及其缓存检查时间点 + if (beforeCallData.timeInfo) { + if (afterCallData.timeInfo) { + afterCallData.timeInfo.requestStartTime = beforeCallData.timeInfo.requestStartTime; + afterCallData.timeInfo.memoryCheckStartTime = beforeCallData.timeInfo.memoryCheckStartTime; + afterCallData.timeInfo.memoryCheckEndTime = beforeCallData.timeInfo.memoryCheckEndTime; + } + } + req.setImageKnifeData(afterCallData); + } + + private initCallData(request: ImageKnifeRequest) { + if (!request) { + return + } + //图片加载信息回调数据 + let callBackData: ImageKnifeData = { + source: '', + imageWidth: 0, + imageHeight: 0, + }; + + //图片加载信息回调数据时间点 + let callBackTimeInfo: TimeInfo = {}; + callBackTimeInfo.requestStartTime = Date.now(); + callBackData.timeInfo = callBackTimeInfo; + + //跟隨請求保存回調信息點 + request.setImageKnifeData(callBackData); + } enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void { + //初始化加载回调信息 + this.initCallData(request); //1.内存有的话直接渲染 if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) { return @@ -105,7 +168,7 @@ export class ImageKnifeDispatcher { } } //3.判断是否要排队 - if (this.executingJobMap.length > this.maxRequests) { + if (this.executingJobMap.length >= this.maxRequests) { this.jobQueue.add(request) return } @@ -113,7 +176,7 @@ export class ImageKnifeDispatcher { } executeJob(request: ImageKnifeRequest,isAnimator?: boolean): void { - LogUtil.log("ImageKnife_DataTime_executeJob.start:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_executeJob.start:' + request.imageKnifeOption.loadSrc) // 加载占位符 if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) { this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) @@ -121,14 +184,19 @@ export class ImageKnifeDispatcher { // 加载主图 this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator) - LogUtil.log("ImageKnife_DataTime_executeJob.end:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_executeJob.end:' + request.imageKnifeOption.loadSrc) } /** * 获取和显示图片 */ getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void { - LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:" + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage.start:' + currentRequest.imageKnifeOption.loadSrc) + if (requestSource === ImageKnifeRequestSource.SRC && currentRequest.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { + currentRequest.imageKnifeOption.onLoadListener?.onLoadStart(currentRequest) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadStart:' + currentRequest.imageKnifeOption.loadSrc) + } + let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator) let requestList: List | undefined = this.executingJobMap.get(memoryKey) if (requestList == undefined) { @@ -141,27 +209,30 @@ export class ImageKnifeDispatcher { } let isWatchProgress : boolean = false + if (currentRequest.imageKnifeOption.progressListener !== undefined && requestSource === ImageKnifeRequestSource.SRC) { + isWatchProgress = true + } // 回调请求开始 requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { - requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart() - LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc) + requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart(requestWithSource.request) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadStart:' + currentRequest.imageKnifeOption.loadSrc) } if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) { isWatchProgress = true } }); - let src: string | number = "" - let moduleName: string = "" - let resName: string = "" + let src: string | number = '' + let moduleName: string = '' + let resName: string = '' if((imageSrc as Resource).id != undefined) { moduleName = (imageSrc as Resource).moduleName src = (imageSrc as Resource).id if(src == -1) { resName = (imageSrc as Resource).params![0] } - } else if(typeof imageSrc == "string") { + } else if(typeof imageSrc == 'string') { src = imageSrc } let request: RequestJobRequest = { @@ -183,38 +254,44 @@ export class ImageKnifeDispatcher { memoryKey: memoryKey, fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(), isAnimator:isAnimator, - moduleName: moduleName == "" ? undefined : moduleName, - resName: resName == "" ? undefined : resName, + moduleName: moduleName == '' ? undefined : moduleName, + resName: resName == '' ? undefined : resName, + caPath: currentRequest.imageKnifeOption.caPath, targetWidth: currentRequest.componentWidth, targetHeight: currentRequest.componentHeight, - downsampType: currentRequest.imageKnifeOption.downsampleOf==undefined?DownsampleStrategy.NONE:currentRequest.imageKnifeOption.downsampleOf, + downsampType: currentRequest.imageKnifeOption.downsampleOf == undefined ? DownsampleStrategy.NONE : currentRequest.imageKnifeOption.downsampleOf } if(request.customGetImage == undefined) { request.customGetImage = ImageKnife.getInstance().getCustomGetImage() } + emitter.on(Constants.CALLBACK_EMITTER + memoryKey,(data)=>{ + emitter.off(Constants.CALLBACK_EMITTER + memoryKey) + let res = data?.data?.value as RequestJobResult | undefined + this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator); + if (isWatchProgress){ + emitter.off(Constants.PROGRESS_EMITTER + memoryKey) + } + LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.end:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage.end:'+currentRequest.imageKnifeOption.loadSrc) + }) if (ImageKnife.getInstance().isRequestInSubThread){ // 启动线程下载和解码主图 - LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:" + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_Task.start:' + currentRequest.imageKnifeOption.loadSrc) let task = new taskpool.Task(requestJob, request) - LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.end:" + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_Task.end:' + currentRequest.imageKnifeOption.loadSrc) if (isWatchProgress){ emitter.on(Constants.PROGRESS_EMITTER + memoryKey, (data) => { this.progressCallBack(requestList! , data?.data?.value as number) }); } - LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(subthread):" + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.start(subthread):' + currentRequest.imageKnifeOption.loadSrc) taskpool.execute(task).then((res: Object) => { - this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator); - if (isWatchProgress){ - emitter.off(Constants.PROGRESS_EMITTER + memoryKey) - } - LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc) - LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc) }).catch((err: BusinessError) => { - LogUtil.error("Fail to requestJob in sub thread src=" + imageSrc + " err=" + err) - LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc) + emitter.off(Constants.CALLBACK_EMITTER + memoryKey) + LogUtil.error('Fail to requestJob in sub thread src=' + imageSrc + ' err=' + err) + LogUtil.log('ImageKnife_DataTime_getAndShowImage.end:' + currentRequest.imageKnifeOption.loadSrc) if (isWatchProgress){ emitter.off(Constants.PROGRESS_EMITTER + memoryKey) } @@ -222,14 +299,12 @@ export class ImageKnifeDispatcher { this.dispatchNextJob(); }) } else { //主线程请求 - LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):" + currentRequest.imageKnifeOption.loadSrc) - requestJob(request, requestList).then((res: RequestJobResult | undefined) => { - this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator); - LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc) - LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):' + currentRequest.imageKnifeOption.loadSrc) + requestJob(request, requestList).then(() => { }).catch((err: BusinessError) => { - LogUtil.error("Fail to requestJob in main thread src=" + imageSrc + " err=" + err) - LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc) + emitter.off(Constants.CALLBACK_EMITTER + memoryKey) + LogUtil.error('Fail to requestJob in main thread src=' + imageSrc + ' err=' + err) + LogUtil.log('ImageKnife_DataTime_getAndShowImage.end:' + currentRequest.imageKnifeOption.loadSrc) this.executingJobMap.remove(memoryKey); this.dispatchNextJob(); }) @@ -252,20 +327,27 @@ export class ImageKnifeDispatcher { private doTaskCallback(requestJobResult: RequestJobResult | undefined, requestList: List , currentRequest: ImageKnifeRequest, memoryKey: string, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean):void { - LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.start:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.start:'+currentRequest.imageKnifeOption.loadSrc) if (requestJobResult === undefined){ return } + + //设置请求结束的时间 + if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) { + requestJobResult.imageKnifeData.timeInfo.requestEndTime = Date.now(); + } + let pixelmap = requestJobResult.pixelMap; if (pixelmap === undefined) { - LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:'+currentRequest.imageKnifeOption.loadSrc) requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { // 回调请求失败 if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined && requestJobResult.loadFail) { - requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail); - LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc) + this.assembleImageKnifeData(requestWithSource.request.getImageKnifeData(), requestJobResult.imageKnifeData, requestWithSource.request) + requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request); + LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadFailed:'+currentRequest.imageKnifeOption.loadSrc) } if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) { @@ -283,17 +365,24 @@ export class ImageKnifeDispatcher { } // 保存文件缓存 if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) { - LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.start:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.start:'+currentRequest.imageKnifeOption.loadSrc) ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize); - LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:'+currentRequest.imageKnifeOption.loadSrc) + } + + let imageKnifeData: ImageKnifeData; + if (!requestJobResult.imageKnifeData) { + imageKnifeData = { + source: pixelmap!, + imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width, + imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height, + type: requestJobResult.type, + }; + } else { + imageKnifeData = requestJobResult.imageKnifeData; + imageKnifeData.source = pixelmap!; } - let ImageKnifeData: ImageKnifeData = { - source: pixelmap!, - imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width, - imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height, - type:requestJobResult.type - }; if(requestJobResult.pixelMapList != undefined) { let imageAnimator: Array = [] requestJobResult.pixelMapList.forEach((item,index)=>{ @@ -302,15 +391,25 @@ export class ImageKnifeDispatcher { duration:requestJobResult.delayList![index] }) }) - ImageKnifeData.imageAnimator = imageAnimator + imageKnifeData.imageAnimator = imageAnimator } + + //构建缓存保存的ImageKnifeData + let saveCacheImageData: ImageKnifeData = { + source: pixelmap!, + imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width, + imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height, + type: requestJobResult.type, + imageAnimator: imageKnifeData.imageAnimator + } + // 保存内存缓存 if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) { - LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:'+currentRequest.imageKnifeOption.loadSrc) ImageKnife.getInstance() .saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator), - ImageKnifeData); - LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc) + saveCacheImageData); + LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:'+currentRequest.imageKnifeOption.loadSrc) } if (requestList !== undefined) { // key相同的request,一起绘制 @@ -321,10 +420,11 @@ export class ImageKnifeDispatcher { requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER || (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER && requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) { - LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_showPixelMap.start:'+currentRequest.imageKnifeOption.loadSrc) requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, - ImageKnifeData.source, requestWithSource.source,ImageKnifeData.imageAnimator); - LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc) + imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight }, + requestWithSource.source, imageKnifeData.imageAnimator); + LogUtil.log('ImageKnife_DataTime_getAndShowImage_showPixelMap.end:'+currentRequest.imageKnifeOption.loadSrc) } if (requestWithSource.source == ImageKnifeRequestSource.SRC) { @@ -332,8 +432,10 @@ export class ImageKnifeDispatcher { if (requestWithSource.request.imageKnifeOption.onLoadListener && requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) { // 回调请求成功 - requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(ImageKnifeData.source,ImageKnifeData); - LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc) + this.assembleImageKnifeData(requestWithSource.request.getImageKnifeData(), imageKnifeData,requestWithSource.request); + requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source, + saveCacheImageData, requestWithSource.request); + LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadSuccess:'+currentRequest.imageKnifeOption.loadSrc) } } else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) { requestWithSource.request.requestState = ImageKnifeRequestState.ERROR; @@ -341,7 +443,19 @@ export class ImageKnifeDispatcher { } else { if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) { // 回调请求成功 - requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") + // 回调请求成功 + //设置失败回调的时间点 + let callBackData = requestWithSource.request.getImageKnifeData(); + + if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) { + requestJobResult.imageKnifeData.timeInfo.requestCancelTime = Date.now(); + if (requestJobResult.imageKnifeData.errorInfo) { + requestJobResult.imageKnifeData.errorInfo.phase = LoadPhase.PHASE_WILL_SHOW; + requestJobResult.imageKnifeData.errorInfo.code = LoadPixelMapCode.IMAGE_LOAD_CANCEL_FAILED_CODE; + } + } + this.assembleImageKnifeData(callBackData,requestJobResult.imageKnifeData,requestWithSource.request) + requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', requestWithSource.request) } } }); @@ -349,27 +463,39 @@ export class ImageKnifeDispatcher { this.executingJobMap.remove(memoryKey); this.dispatchNextJob(); } else { - LogUtil.log("error: no requestlist need to draw for key = " + memoryKey); + LogUtil.log('error: no requestlist need to draw for key = ' + memoryKey); } - LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.end:"+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.end:'+currentRequest.imageKnifeOption.loadSrc) } dispatchNextJob() { - LogUtil.log("ImageKnife_DataTime_dispatchNextJob.start") + LogUtil.log('ImageKnife_DataTime_dispatchNextJob.start') while (true) { let request = this.jobQueue.pop() if (request === undefined) { - LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end:no any job") + LogUtil.log('ImageKnife_DataTime_dispatchNextJob.end:no any job') break // 队列已无任务 } else if (request.requestState === ImageKnifeRequestState.PROGRESS) { - LogUtil.log("ImageKnife_DataTime_dispatchNextJob.start executeJob:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_dispatchNextJob.start executeJob:' + request.imageKnifeOption.loadSrc) this.executeJob(request) - LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc) + LogUtil.log('ImageKnife_DataTime_dispatchNextJob.end executeJob:' + request.imageKnifeOption.loadSrc) break }else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) { - request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") + //构建回调错误信息 + let callBackData = request.getImageKnifeData(); + if (callBackData) { + let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData) + timeInfo.requestCancelTime = Date.now(); + timeInfo.requestEndTime = Date.now() + let errorInfo: ErrorInfo = { + phase: LoadPhase.PHASE_THREAD_QUEUE, + code: LoadPixelMapCode.IMAGE_LOAD_CANCEL_FAILED_CODE, + }; + callBackData.errorInfo = errorInfo; + } + request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', request) } } } @@ -396,44 +522,15 @@ export class ImageKnifeDispatcher { * @returns */ @Concurrent -async function requestJob(request: RequestJobRequest, requestList?: List): Promise { - LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src + " requestSource=" + request.requestSource) - let src = typeof request.src == "number" ? request.resName != undefined ? request.resName : request.src + "" : request.src +async function requestJob(request: RequestJobRequest, requestList?: List) { + LogUtil.log('ImageKnife_DataTime_requestJob.start:' + request.src + ' requestSource=' + request.requestSource) + let src = typeof request.src == 'number' ? request.resName != undefined ? request.resName : request.src + '' : request.src // 生成文件缓存key let fileKey = request.engineKey.generateFileKey(src, request.signature, request.isAnimator) //获取图片资源 - let resBuf: ArrayBuffer - try { - LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.start:" + request.src) - resBuf = await ImageKnifeLoader.getImageArrayBuffer(request, requestList, fileKey) - LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.end:" + request.src) - } catch (error) { - LogUtil.error("ImageKnife_DataTime_requestJob.end: getImageArrayBuffer error " + request.src + " err=" + error) - return ImageKnifeLoader.makeEmptyResult(error) - } + ImageKnifeLoader.execute(request,requestList,fileKey) - // 获取图片类型 - let typeValue = new FileTypeUtil().getFileType(resBuf); - if(typeValue == null) { - LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src) - return ImageKnifeLoader.makeEmptyResult("request is not a valid image source") - } - - // 解析图片 - LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.start:" + request.src) - let result: RequestJobResult = await ImageKnifeLoader.parseImage(resBuf, typeValue, fileKey, request) - LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.end:" + request.src) - - // 图形变化 - if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && result?.pixelMap !== undefined && typeof result.pixelMap !== 'string') { - LogUtil.log("ImageKnife_DataTime_requestJob.transform.start:" + request.src) - result.pixelMap = await request.transformation?.transform(request.context, result.pixelMap, request.componentWidth, request.componentHeight); - LogUtil.log("ImageKnife_DataTime_requestJob.transform.end:" + request.src) - } - - LogUtil.log("ImageKnife_DataTime_requestJob.end:" + request.src) - return result } diff --git a/library/src/main/ets/ImageKnifeLoader.ets b/library/src/main/ets/ImageKnifeLoader.ets index b00e5fb..34aff71 100644 --- a/library/src/main/ets/ImageKnifeLoader.ets +++ b/library/src/main/ets/ImageKnifeLoader.ets @@ -14,12 +14,16 @@ */ import { CacheStrategy, + DecodeImageInfo, + ErrorInfo, + ImageKnifeData, ImageKnifeRequestSource, - ImageKnifeRequestWithSource, RequestJobRequest } from './model/ImageKnifeData'; + ImageKnifeRequestWithSource, RequestJobRequest, + TimeInfo } from './model/ImageKnifeData'; import List from '@ohos.util.List' import { FileCache } from './cache/FileCache'; import { LogUtil } from './utils/LogUtil'; -import { Constants } from './utils/Constants'; +import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants'; import http from '@ohos.net.http'; import { combineArrayBuffers } from './utils/ArrayBufferUtils'; import { BusinessError } from '@kit.BasicServicesKit'; @@ -28,6 +32,7 @@ import emitter from '@ohos.events.emitter'; import image from '@ohos.multimedia.image'; import { RequestJobResult } from './model/ImageKnifeData' import util from '@ohos.util'; +import { FileTypeUtil } from './utils/FileTypeUtil'; import { DownsampleStrategy } from './downsampling/DownsampleStartegy'; import { Downsampler } from './downsampling/Downsampler'; @@ -40,73 +45,153 @@ class RequestData { * ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法,故抽取到另一个类 */ export class ImageKnifeLoader { - static async parseImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, - request: RequestJobRequest): Promise { + static execute(request: RequestJobRequest, requestList: List | undefined, fileKey: string){ + ImageKnifeLoader.getImageArrayBuffer(request,requestList,fileKey) + } + static async parseImage(resBuf: ArrayBuffer, fileKey: string, + request: RequestJobRequest, callBackData: ImageKnifeData) { + callBackData.bufSize = resBuf.byteLength; + let typeValue = new FileTypeUtil().getFileType(resBuf); + if(typeValue == null) { + LogUtil.log('ImageKnife_DataTime_requestJob.end: getFileType is null ' + request.src) + ImageKnifeLoader.makeEmptyResult(request,'request is not a valid image source', ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT, LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE)) + return + } + callBackData.type = typeValue; if(request.isAnimator) { - return ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request) + ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request, callBackData) + return } if (typeValue === 'gif' || typeValue === 'webp') { - return ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request) - } else if(typeValue == "svg") { - return ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request) + ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request, callBackData) + return + } else if(typeValue == 'svg') { + ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request, callBackData) + return } - return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request) + ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request, callBackData) } - static makeEmptyResult(error: string): RequestJobResult{ - return { + static makeEmptyResult(request:RequestJobRequest,error: string, data?: ImageKnifeData){ + let res: RequestJobResult = { pixelMap: undefined, bufferSize: 0, fileKey: '', loadFail: error, + imageKnifeData: data } + emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } }) } - static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest):Promise { + static assembleError(data: ImageKnifeData | undefined, phase: string, code?: number, + httpCode?: number): ImageKnifeData | undefined { + let errorCallBackData = data?.errorInfo; + if (!errorCallBackData) { + return data; + } + errorCallBackData.phase = phase; + errorCallBackData.code = code? code: 0; + if (httpCode && httpCode != 0) { + errorCallBackData.httpCode = httpCode; + } + return data + } + + static getTimeInfo(callBackData: ImageKnifeData): TimeInfo { + let timeInfo: TimeInfo; + if (callBackData.timeInfo) { + timeInfo = callBackData.timeInfo; + }else { + timeInfo = {}; + callBackData.timeInfo = timeInfo; + } + return timeInfo; + } + + static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest, callBackData: ImageKnifeData) { let resPixelmap: PixelMap | undefined = undefined + let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData); + let decodingOptions: image.DecodingOptions = { editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false, } let imageSource: image.ImageSource = image.createImageSource(resBuf) if (imageSource === undefined){ - return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") + ImageKnifeLoader.makeEmptyResult(request,'image.createImageSource failed', ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE)) + return } let size = (await imageSource.getImageInfo()).size + callBackData.imageWidth = size.width; + callBackData.imageHeight = size.height; try { if ((request.downsampType !== DownsampleStrategy.NONE) && request.requestSource == ImageKnifeRequestSource.SRC) { - decodingOptions = ImageKnifeLoader.getDownsamplerDecodingOptions(typeValue, request, size, ImageKnifeRequestSource.SRC) + decodingOptions = + ImageKnifeLoader.getDownsamplerDecodingOptions(typeValue, request, size, ImageKnifeRequestSource.SRC) } } catch (err) { - return ImageKnifeLoader.makeEmptyResult(err) + ImageKnifeLoader.makeEmptyResult(request, err) + return } + timeInfo.decodeStartTime = Date.now(); await imageSource.createPixelMap(decodingOptions) .then((pixelmap: PixelMap) => { + timeInfo.decodeEndTime = Date.now(); resPixelmap = pixelmap imageSource.release() }).catch((error: BusinessError) => { + timeInfo.decodeEndTime = Date.now(); imageSource.release() - return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error)) + ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_PIXEL_MAP, LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE)) + return }) + if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) { + LogUtil.log('ImageKnife_DataTime_requestJob.transform.start:' + request.src) + resPixelmap = await request.transformation?.transform(request.context, resPixelmap, request.componentWidth, request.componentHeight); + LogUtil.log('ImageKnife_DataTime_requestJob.transform.end:' + request.src) + } + try { + resPixelmap?.setTransferDetached(true) + } catch (e) { + LogUtil.error('PixelMap setTransferDetached err:'+JSON.stringify(e)) + } - return { + //获取各个pixelMap的大小 + if (resPixelmap && typeof resPixelmap !== 'string') { + let decodeImages: DecodeImageInfo[] = []; + let size = (resPixelmap as PixelMap).getImageInfoSync().size; + let decodeImage: DecodeImageInfo = { + contentWidth: size.width, + contentHeight: size.height, + contentSize: (resPixelmap as PixelMap).getPixelBytesNumber() + } + decodeImages.push(decodeImage); + callBackData.decodeImages = decodeImages; + } + + let res: RequestJobResult = { pixelMap: resPixelmap, bufferSize: resBuf.byteLength, fileKey: fileKey, size:size, - type:typeValue - }; + type:typeValue, + imageKnifeData:callBackData + } + emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } }) } static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, - request: RequestJobRequest): Promise { + request: RequestJobRequest, callBackData: ImageKnifeData) { let resPixelmap: PixelMap | undefined = undefined + let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData); + let imageSource: image.ImageSource = image.createImageSource(resBuf) if (imageSource === undefined){ - return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") + ImageKnifeLoader.makeEmptyResult(request,'image.createImageSource failed', ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE)) + return } let size = (await imageSource.getImageInfo()).size @@ -121,67 +206,111 @@ export class ImageKnifeLoader { editable: true, desiredSize: defaultSize }; + callBackData.imageWidth = size.width; + callBackData.imageHeight = size.height; try { if ((request.downsampType !== DownsampleStrategy.NONE) && request.requestSource == ImageKnifeRequestSource.SRC) { opts = ImageKnifeLoader.getDownsamplerDecodingOptions(typeValue, request, size) } } catch (err) { - return ImageKnifeLoader.makeEmptyResult(err) + ImageKnifeLoader.makeEmptyResult(request,err) + return } + timeInfo.decodeStartTime = Date.now(); await imageSource.createPixelMap(opts) .then((pixelmap: PixelMap) => { + timeInfo.decodeEndTime = Date.now(); resPixelmap = pixelmap imageSource.release() + try { + resPixelmap.setTransferDetached(true) + } catch (e) { + LogUtil.error('PixelMap setTransferDetached err:'+JSON.stringify(e)) + } }).catch((error: BusinessError) => { + timeInfo.decodeEndTime = Date.now(); imageSource.release() - return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error)) + ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_PIXEL_MAP, LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE)) + return }) - return { + //获取各个pixelMap的大小 + if (resPixelmap && typeof resPixelmap !== 'string') { + let decodeImages: DecodeImageInfo[] = []; + let decodeImage: DecodeImageInfo = { + contentWidth: defaultSize.width, + contentHeight: defaultSize.height, + contentSize: (resPixelmap as PixelMap).getPixelBytesNumber() + } + decodeImages.push(decodeImage); + } + + let res: RequestJobResult = { pixelMap: resPixelmap, bufferSize: resBuf.byteLength, fileKey: fileKey, - type:typeValue - }; + type:typeValue, + imageKnifeData:callBackData + } + emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } }) } static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string, - fileKey: string,request: RequestJobRequest): Promise { + fileKey: string,request: RequestJobRequest, callBackData: ImageKnifeData) { + let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData); let imageSource: image.ImageSource = image.createImageSource(resBuf) if (imageSource === undefined){ - return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") + ImageKnifeLoader.makeEmptyResult(request,'image.createImageSource failed', ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CREATE_SOURCE,LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE)) + return } let frameCount = await imageSource.getFrameCount() let size = (await imageSource.getImageInfo()).size + callBackData.frameCount = frameCount; + callBackData.imageWidth = size.width; + callBackData.imageHeight = size.height; + imageSource.release() if(frameCount == undefined || frameCount == 1) { } else { - let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf)) - return { + timeInfo.decodeStartTime = Date.now() + let base64str = 'data:image/' + typeValue + ';base64,' + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf)) + timeInfo.diskCheckEndTime = Date.now() + let res: RequestJobResult = { pixelMap: base64str, bufferSize: resBuf.byteLength, fileKey: fileKey, size:size, - type:typeValue - }; + type:typeValue, + imageKnifeData:callBackData + } + emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } }) + return } - return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request) + ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request, callBackData) } // 为AnimatorComponent解析动图 - static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest): Promise { + static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest, callBackData: ImageKnifeData) { + let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData); + if (typeValue === 'gif' || typeValue === 'webp') { let imageSource: image.ImageSource = image.createImageSource(resBuf); if (imageSource === undefined){ - return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") + ImageKnifeLoader.makeEmptyResult(request,'image.createImageSource failed', ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE)) + return } let decodingOptions: image.DecodingOptions = { editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false, } + callBackData.imageWidth = imageSource.getImageInfoSync().size.width; + callBackData.imageHeight = imageSource.getImageInfoSync().size.height; let pixelMapList: Array = [] let delayList: Array = [] + timeInfo.decodeStartTime = Date.now(); + let decodeImages: Array = []; await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array) => { + timeInfo.decodeEndTime = Date.now(); //sdk的api接口发生变更:从.getDelayTime() 变为.getDelayTimeList() await imageSource.getDelayTimeList().then(delayTimes => { if (pixelList.length > 0) { @@ -192,78 +321,127 @@ export class ImageKnifeLoader { } else { delayList.push(delayTimes[delayTimes.length - 1]) } + //获取各个pixelMap的大小 + let size = pixelList[i].getImageInfoSync().size + let decodeImage: DecodeImageInfo = { + contentWidth: size.width, + contentHeight: size.height, + contentSize: pixelList[i].getPixelBytesNumber() + } + decodeImages.push(decodeImage); } imageSource.release(); } }) }).catch((error: BusinessError) => { imageSource.release() - return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error)) + timeInfo.decodeEndTime = Date.now(); + ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CREATE_PIXEL_MAP,LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE)) + return }) - return { - pixelMap: "", + callBackData.decodeImages = decodeImages; + let res: RequestJobResult = { + pixelMap: '', bufferSize: resBuf.byteLength, fileKey: fileKey, type: typeValue, + imageKnifeData:callBackData, pixelMapList, delayList } + emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } }) } else { - return ImageKnifeLoader.makeEmptyResult("ImageKnifeAnimatorComponent组件仅支持动态图") + ImageKnifeLoader.makeEmptyResult(request,'ImageKnifeAnimatorComponent组件仅支持动态图', ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_PARSE_IAMGE,LoadPixelMapCode.IMAGE_FORMAT_ERROR_CODE)) } } - + static getHeaderObj(request:RequestJobRequest){ + const headerObj: Record = {} + if (request.headers != undefined) { + request.headers.forEach((value) => { + headerObj[value.key] = value.value + }) + } else if (request.allHeaders.size > 0) { + request.allHeaders.forEach((value, key) => { + headerObj[key] = value + }) + } + return headerObj + } + static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string, callBackData: ImageKnifeData){ + // 保存文件缓存 + if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) { + LogUtil.log('ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:'+request.src) + FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder) + LogUtil.log('ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:'+request.src) + } + ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData) + } // 获取图片资源 - static async getImageArrayBuffer(request: RequestJobRequest, requestList: List | undefined,fileKey:string): Promise { + static async getImageArrayBuffer(request: RequestJobRequest, requestList: List | undefined,fileKey:string) { let resBuf: ArrayBuffer | undefined + let loadError: string = '' + //定义图片各个阶段错误信息 + let error: ErrorInfo = { code: 0, phase: LoadPhase.PHASE_LOAD } + //定义加载时间点 + let callBackTimeInfo: TimeInfo = {}; + //定义加载信息回调数据 + let callBackData: ImageKnifeData = { + source: '', + imageWidth: 0, + imageHeight: 0, + timeInfo: callBackTimeInfo, + errorInfo: error + }; // 判断自定义下载 - if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") { + if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == 'string') { // 先从文件缓存获取 + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CUSTOM_LOAD) + callBackTimeInfo.diskCheckStartTime = Date.now(); resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) + callBackTimeInfo.diskCheckEndTime = Date.now(); if (resBuf === undefined) { - LogUtil.log("start customGetImage src=" + request.src) + LogUtil.log('start customGetImage src=' + request.src) + const headerObj: Record = ImageKnifeLoader.getHeaderObj(request) try { - resBuf = await request.customGetImage(request.context, request.src) - LogUtil.log("end customGetImage src=" + request.src) - } catch (err) { - throw new Error('customGetImage loadFile failed! err = ' + err) - } - if (resBuf === undefined) { - throw new Error('customGetImage loadFile failed!') - } - // 保存文件缓存 - if (request.writeCacheStrategy !== CacheStrategy.Memory) { - LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:" + request.src) - FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf, request.fileCacheFolder) - LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:" + request.src) + request.customGetImage(request.context, request.src, headerObj) + .then((buffer)=>{ + if(buffer != undefined) { + ImageKnifeLoader.FileCacheParseImage(request,buffer,fileKey,callBackData) + } else { + loadError = 'customGetImage loadFail undefined' + ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE)) + } + }).catch((err:string)=>{ + ImageKnifeLoader.makeEmptyResult(request,err, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE)) + }) + } catch (e) { + loadError = 'customGetImage loadFail failed' + ImageKnifeLoader.makeEmptyResult(request,loadError + e, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE)) } + LogUtil.log('end customGetImage src=' + request.src) + return } } else { if (typeof request.src === 'string') { - if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载 + if (request.src.indexOf('http://') == 0 || request.src.indexOf('https://') == 0) { //从网络下载 // 先从文件缓存获取 + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET) + callBackTimeInfo.diskCheckStartTime = Date.now() resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) + callBackTimeInfo.diskCheckEndTime = Date.now() if (resBuf !== undefined){ - LogUtil.log("success get image from filecache for key = " + fileKey + " src = " + request.src) + LogUtil.log('success get image from filecache for key = ' + fileKey + ' src = ' + request.src) } else if (request.onlyRetrieveFromCache != true) { - LogUtil.log("HttpDownloadClient.start:" + request.src) + LogUtil.log('HttpDownloadClient.start:' + request.src) + callBackTimeInfo.netRequestStartTime = Date.now(); let httpRequest = http.createHttp(); let progress: number = 0 - let arrayBuffers = new Array() - const headerObj: Record = {} - if (request.headers != undefined) { - request.headers.forEach((value) => { - headerObj[value.key] = value.value - }) - } else if (request.allHeaders.size > 0) { - request.allHeaders.forEach((value, key) => { - headerObj[key] = value - }) - } - httpRequest.on("dataReceive", (data: ArrayBuffer) => { + let arrayBuffers:ArrayBuffer[] = [] + const headerObj: Record = ImageKnifeLoader.getHeaderObj(request) + httpRequest.on('dataReceive', (data: ArrayBuffer) => { arrayBuffers.push(data) }); @@ -276,7 +454,7 @@ export class ImageKnifeLoader { progress = percent if (requestList === undefined) { // 子线程 - emitter.emit(Constants.PROGRESS_EMITTER + request.memoryKey, { data: { "value": progress } }) + emitter.emit(Constants.PROGRESS_EMITTER + request.memoryKey, { data: { 'value': progress } }) }else { // 主线程请求 requestList!.forEach((requestWithSource: ImageKnifeRequestWithSource) => { @@ -297,29 +475,33 @@ export class ImageKnifeLoader { readTimeout: 0, // usingProtocol:http.HttpProtocol.HTTP1_1 // header: new Header('application/json') + caPath: request.caPath === undefined ? undefined : request.caPath, }); - await promise.then((data: number) => { + promise.then((data: number) => { + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, undefined, data) + callBackTimeInfo.netRequestEndTime = Date.now(); if (data == 200 || data == 206 || data == 204) { resBuf = combineArrayBuffers(arrayBuffers) + ImageKnifeLoader.FileCacheParseImage(request,resBuf,fileKey, callBackData) } else { - throw new Error("HttpDownloadClient has error, http code =" + JSON.stringify(data)) + loadError = 'HttpDownloadClient has error, http code =' + JSON.stringify(data) + ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE, data)) } }).catch((err: Error) => { - throw new Error("HttpDownloadClient download ERROR : err = " + JSON.stringify(err)) + loadError = 'HttpDownloadClient download ERROR : err = ' + JSON.stringify(err) + callBackTimeInfo.netRequestEndTime = Date.now(); + ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE, undefined)) }); - LogUtil.log("HttpDownloadClient.end:" + request.src) - // 保存文件缓存 - if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) { - LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src) - FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder) - LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src) - } + LogUtil.log('HttpDownloadClient.end:' + request.src) + return } else { - throw new Error('onlyRetrieveFromCache,do not fetch image src = ' + request.src) + callBackTimeInfo.netRequestEndTime = Date.now(); + loadError = 'onlyRetrieveFromCache,do not fetch image src = ' + request.src } } else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) { + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE) await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => { await fs.stat(file.fd).then(async (stat) =>{ let buf = new ArrayBuffer(stat.size); @@ -327,15 +509,19 @@ export class ImageKnifeLoader { resBuf = buf; fs.closeSync(file.fd); }).catch((err:BusinessError) => { - throw new Error('LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code) + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE) + loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + ' err.msg=' + err?.message + ' err.code=' + err?.code }) }).catch((err:BusinessError) => { - throw new Error('LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code) + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE) + loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + ' err.msg=' + err?.message + ' err.code=' + err?.code }) }).catch((err:BusinessError) => { - throw new Error('LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code) + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE) + loadError = 'LoadDataShareFileClient fs.open err happened uri=' + request.src + ' err.msg=' + err?.message + ' err.code=' + err?.code }) } else { //从本地文件获取 + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE) try { let stat = fs.statSync(request.src); if (stat.size > 0) { @@ -345,10 +531,11 @@ export class ImageKnifeLoader { fs.closeSync(file); } } catch (err) { - throw new Error(err) + ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE, LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE) + loadError = err } } - } else if (typeof request.src == "number") { //从资源文件获取 + } else if (typeof request.src == 'number') { //从资源文件获取 let manager = request.context.createModuleContext(request.moduleName).resourceManager if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) { if(request.src == -1) { @@ -369,17 +556,19 @@ export class ImageKnifeLoader { } if (resBuf === undefined){ - throw new Error('getImageArrayBuffer undefined') + callBackTimeInfo.requestEndTime = Date.now(); + ImageKnifeLoader.makeEmptyResult(request,loadError ,callBackData) + return } - return resBuf + ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData) } - static getDownsamplerDecodingOptions(typeValue: string, request: RequestJobRequest, size: Size, + static getDownsamplerDecodingOptions(typeValue: string, request: RequestJobRequest, size: Size, SRC?: ImageKnifeRequestSource):image.DecodingOptions { let reqSize = new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth, request.targetHeight, request.downsampType) - if (typeValue == "svg") { + if (typeValue == 'svg') { return { editable: true, desiredSize: { @@ -398,5 +587,4 @@ export class ImageKnifeLoader { } } } -} - +} \ No newline at end of file diff --git a/library/src/main/ets/cache/FileCache.ets b/library/src/main/ets/cache/FileCache.ets index 41978b8..afffb48 100644 --- a/library/src/main/ets/cache/FileCache.ets +++ b/library/src/main/ets/cache/FileCache.ets @@ -25,11 +25,11 @@ const INT_MAX = 2147483647 * 子线程直接读写文件 */ export class FileCache { - static CACHE_FOLDER: string = "ImageKnife" // context cacheDir 的缓存文件目录 + static CACHE_FOLDER: string = 'ImageKnife' // context cacheDir 的缓存文件目录 maxMemory: number = 0 currentMemory: number = 0 maxSize: number = 0 - path: string = "" + path: string = '' private lruCache: util.LRUCache private isInited: boolean = false private context?: Context @@ -153,11 +153,11 @@ export class FileCache { this.remove(this.lruCache.keys()[0]) } else if (this.lruCache.contains(key)) { this.lruCache.remove(key) - this.lruCache.put(key, typeof value == "number" ? value : value.byteLength) + this.lruCache.put(key, typeof value == 'number' ? value : value.byteLength) return } - this.lruCache.put(key, typeof value == "number" ? value : value.byteLength) + this.lruCache.put(key, typeof value == 'number' ? value : value.byteLength) this.addMemorySize(value) this.trimToSize() } @@ -227,23 +227,23 @@ export class FileCache { } private removeMemorySize(value: ArrayBuffer | number): void { - if (typeof value == "number") { + if (typeof value == 'number') { this.currentMemory -= value } else if (value != undefined) { this.currentMemory -= value.byteLength - LogUtil.debug("FileCache removeMemorySize: " + value.byteLength + " currentMemory:" + this.currentMemory) + LogUtil.debug('FileCache removeMemorySize: ' + value.byteLength + ' currentMemory:' + this.currentMemory) } } private addMemorySize(value: ArrayBuffer | number): void { - if (typeof value == "number") { + if (typeof value == 'number') { this.currentMemory += value - LogUtil.debug("FileCache addMemorySize: " + value + " currentMemory:" + this.currentMemory) + LogUtil.debug('FileCache addMemorySize: ' + value + ' currentMemory:' + this.currentMemory) } else if (value != undefined) { this.currentMemory += value.byteLength - LogUtil.debug("FileCache addMemorySize: " + value.byteLength + " currentMemory:" + this.currentMemory) + LogUtil.debug('FileCache addMemorySize: ' + value.byteLength + ' currentMemory:' + this.currentMemory) } } @@ -279,13 +279,13 @@ export class FileCache { */ getFileToPath(key: string): string { if(!!!key) { - throw new Error("key is null,checking the parameter") + throw new Error('key is null,checking the parameter') } let path = this.path + key if(FileUtils.getInstance().exist(path)) { return path } else { - return "" + return '' } } } \ No newline at end of file diff --git a/library/src/main/ets/cache/MemoryLruCache.ets b/library/src/main/ets/cache/MemoryLruCache.ets index 493fc11..282907f 100644 --- a/library/src/main/ets/cache/MemoryLruCache.ets +++ b/library/src/main/ets/cache/MemoryLruCache.ets @@ -46,6 +46,11 @@ export class MemoryLruCache implements IMemoryCache { throw new Error('key or value is invalid '); } + let size = this.getImageKnifeDataSize(value) + if (size <= 0 || size >= this.maxMemory) { + return + } + // 如果size满了的话,需要按照LRU的方式删除第一个 if (this.lruCache.length == this.maxSize && !this.lruCache.contains(key)) { this.remove(this.lruCache.keys()[0]) @@ -53,12 +58,9 @@ export class MemoryLruCache implements IMemoryCache { this.remove(key) } - let pre: ImageKnifeData = this.lruCache.put(key, value) - this.addMemorySize(value) - // if (pre !== undefined) { // 当前返回不是key的之前value - // this.removeMemorySize(pre) - // } - this.trimToSize(); + this.lruCache.put(key, value) + this.currentMemory += size + this.trimToSize() } get(key: string): ImageKnifeData | undefined { @@ -104,9 +106,9 @@ export class MemoryLruCache implements IMemoryCache { private removeMemorySize(value: ImageKnifeData): void { if (value.source != undefined) { - if (typeof value.source === 'string' && value.source != "") { + if (typeof value.source === 'string' && value.source != '') { this.currentMemory -= value.source.length - } else if (value.source == "") { + } else if (value.source == '') { for (let index = 0;index < value.imageAnimator!.length;index++) { let pixelMap = value.imageAnimator![index].src as PixelMap this.currentMemory -= pixelMap.getPixelBytesNumber() @@ -115,23 +117,25 @@ export class MemoryLruCache implements IMemoryCache { this.currentMemory -= value.source.getPixelBytesNumber(); value.source.release() } - // LogUtil.info("MemoryCache removeMemorySize: " + value.source.getPixelBytesNumber() + " currentMemory:" + this.currentMemory) + // LogUtil.info('MemoryCache removeMemorySize: ' + value.source.getPixelBytesNumber() + ' currentMemory:' + this.currentMemory) } } - private addMemorySize(value: ImageKnifeData): void { + private getImageKnifeDataSize(value: ImageKnifeData): number { if (value.source != undefined) { - if (typeof value.source === 'string' && value.source != "") { - this.currentMemory += value.source.length - } else if (value.source == "") { - for (let index = 0;index < value.imageAnimator!.length;index++) { + if (typeof value.source === 'string' && value.source != '') { + return value.source.length + } else if (value.source == '') { + let size: number = 0 + for (let index = 0; index < value.imageAnimator!.length; index++) { let pixelMap = value.imageAnimator![index].src as PixelMap - this.currentMemory += pixelMap.getPixelBytesNumber() + size += pixelMap.getPixelBytesNumber() } + return size } else { - this.currentMemory += value.source.getPixelBytesNumber(); + return value.source.getPixelBytesNumber(); } - //LogUtil.log("MemoryCache addMemorySize: " + value.source.getPixelBytesNumber() + " currentMemory:" + this.currentMemory) } + return 0 } } \ No newline at end of file diff --git a/library/src/main/ets/components/ImageKnifeAnimatorComponent.ets b/library/src/main/ets/components/ImageKnifeAnimatorComponent.ets index 93cdf84..67816a3 100644 --- a/library/src/main/ets/components/ImageKnifeAnimatorComponent.ets +++ b/library/src/main/ets/components/ImageKnifeAnimatorComponent.ets @@ -19,14 +19,15 @@ import { ImageKnife } from '../ImageKnife'; import { LogUtil } from '../utils/LogUtil'; import { ImageKnifeRequestSource } from '../model/ImageKnifeData'; -@ComponentV2 +@Component export struct ImageKnifeAnimatorComponent { - @Param animatorOption: AnimatorOption = new AnimatorOption(); - @Local pixelMap: PixelMap | string | undefined = undefined - @Local imageAnimator: Array | undefined = undefined - @Local adaptiveWidth: Length = '100%' - @Local adaptiveHeight: Length = '100%' - @Local objectFit: ImageFit = ImageFit.Contain + @Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption; + @State animatorOption: AnimatorOption = new AnimatorOption(); + @State pixelMap: PixelMap | string | undefined = undefined + @State imageAnimator: Array | undefined = undefined + @State adaptiveWidth: Length = '100%' + @State adaptiveHeight: Length = '100%' + @State objectFit: ImageFit = ImageFit.Contain private request: ImageKnifeRequest | undefined private lastWidth: number = 0 private lastHeight: number = 0 @@ -34,17 +35,7 @@ export struct ImageKnifeAnimatorComponent { private currentHeight: number = 0 private componentVersion: number = 0 private currentContext: common.UIAbilityContext | undefined = undefined - @Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption(); - @Monitor('imageKnifeOption', - "imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit") - watchImageKnifeOption() { - if (this.request !== undefined) { - this.request.requestState = ImageKnifeRequestState.DESTROY - } - this.request = undefined - this.componentVersion++ - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) - } + aboutToAppear(): void { this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit } @@ -83,7 +74,7 @@ export struct ImageKnifeAnimatorComponent { } else { // 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制 if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) { - LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight) + LogUtil.log('execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight) ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true) } } @@ -95,6 +86,15 @@ export struct ImageKnifeAnimatorComponent { .onRepeat(this.animatorOption.onRepeat) } + watchImageKnifeOption() { + if (this.request !== undefined) { + this.request.requestState = ImageKnifeRequestState.DESTROY + } + this.request = undefined + this.componentVersion++ + ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true) + } + getCurrentContext(): common.UIAbilityContext { if (this.currentContext == undefined) { this.currentContext = getContext(this) as common.UIAbilityContext @@ -111,7 +111,7 @@ export struct ImageKnifeAnimatorComponent { height, this.componentVersion, { - showPixelMap: async (version: number, pixelMap: PixelMap | string, requestSource: ImageKnifeRequestSource,imageAnimator?: Array) => { + showPixelMap: (version: number, pixelMap: PixelMap | string,size: Size, requestSource: ImageKnifeRequestSource,imageAnimator?: Array) => { if (version !== this.componentVersion) { return //针对reuse场景,不显示历史图片 } diff --git a/library/src/main/ets/components/ImageKnifeComponent.ets b/library/src/main/ets/components/ImageKnifeComponent.ets index 59812e9..ed30334 100644 --- a/library/src/main/ets/components/ImageKnifeComponent.ets +++ b/library/src/main/ets/components/ImageKnifeComponent.ets @@ -21,13 +21,14 @@ import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData import { IEngineKey } from '../key/IEngineKey'; import { DefaultEngineKey } from '../key/DefaultEngineKey'; -@ComponentV2 +@Component export struct ImageKnifeComponent { - @Local pixelMap: PixelMap | string | undefined = undefined - @Param syncLoad: boolean = false - @Local adaptiveWidth: Length = '100%' - @Local adaptiveHeight: Length = '100%' - @Local objectFit: ImageFit = ImageFit.Contain + @Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption; + @State pixelMap: PixelMap | string | ImageContent | undefined = undefined + @State syncLoad: boolean = false + @State adaptiveWidth: Length = '100%' + @State adaptiveHeight: Length = '100%' + @State objectFit: ImageFit = ImageFit.Contain private request: ImageKnifeRequest | undefined private lastWidth: number = 0 private lastHeight: number = 0 @@ -35,20 +36,6 @@ export struct ImageKnifeComponent { private currentHeight: number = 0 private componentVersion: number = 0 private currentContext: common.UIAbilityContext | undefined = undefined - @Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption(); - - @Monitor('imageKnifeOption', - "imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit",'imageKnifeOption.downsampleOf') - watchImageKnifeOption() { - this.clearLastRequest() - this.componentVersion++ - this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit - LogUtil.log("watchImageKnifeOption execute request:width=" + this.currentWidth + " height= " + this.currentHeight - + " loadSrc = " + this.request?.imageKnifeOption.loadSrc - + " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc - + " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc) - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) - } aboutToAppear(): void { this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit @@ -58,18 +45,18 @@ export struct ImageKnifeComponent { let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance() .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption)) if (memoryCacheSrc !== undefined){ - LogUtil.log("aboutToAppear success load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc) + LogUtil.log('aboutToAppear success load loadSrc from memory cache for loadSrc = '+ this.imageKnifeOption.loadSrc) this.pixelMap = memoryCacheSrc.source; }else{ - LogUtil.log("aboutToAppear fail load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc) + LogUtil.log('aboutToAppear fail load loadSrc from memory cache for loadSrc = '+ this.imageKnifeOption.loadSrc) if (this.imageKnifeOption.placeholderSrc !== undefined){ let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance() .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption)) if (memoryCachePlace !== undefined){ - LogUtil.log("aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc) + LogUtil.log('aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = ' + this.imageKnifeOption.placeholderSrc) this.pixelMap = memoryCachePlace.source; }else{ - LogUtil.log("aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc) + LogUtil.log('aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = ' + this.imageKnifeOption.placeholderSrc) } } } @@ -81,9 +68,9 @@ export struct ImageKnifeComponent { } aboutToRecycle() { + this.pixelMap = ImageContent.EMPTY this.clearLastRequest() } - /** * 对已DESTROY的组件不再发起请求 */ @@ -93,7 +80,6 @@ export struct ImageKnifeComponent { this.request = undefined } } - build() { Image(this.pixelMap) .colorFilter(this.imageKnifeOption.drawingColorFilter) @@ -109,19 +95,29 @@ export struct ImageKnifeComponent { this.currentHeight = newValue.height as number this.lastWidth = oldValue.width as number this.lastHeight = oldValue.height as number - - // 条件1: 宽高值均有效,值>0. 条件2:当前宽高与上一次宽高不同 - if (this.currentWidth > 0 && this.currentHeight > 0 && - (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth)) { - LogUtil.log("onSizeChange execute request:width=" + this.currentWidth + " height= " + this.currentHeight - + " loadSrc = " + this.request?.imageKnifeOption.loadSrc - + " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc - + " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc) - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) + if (this.currentWidth <= 0 || this.currentHeight <= 0) { + // 存在宽或者高为0,此次重回无意义,无需进行request请求 + } else { + // 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制 + if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) { + LogUtil.log('execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight) + ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) + } } }) } + watchImageKnifeOption() { + this.clearLastRequest() + this.componentVersion++ + this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit + LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight + + ' loadSrc = ' + this.request?.imageKnifeOption.loadSrc + + ' placeholderSrc = ' + this.request?.imageKnifeOption.placeholderSrc + + ' errorholderSrc = ' + this.request?.imageKnifeOption.errorholderSrc) + ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) + } + getCurrentContext(): common.UIAbilityContext { if (this.currentContext == undefined) { this.currentContext = getContext(this) as common.UIAbilityContext @@ -138,15 +134,16 @@ export struct ImageKnifeComponent { height, this.componentVersion, { - showPixelMap: async (version: number, pixelMap: PixelMap | string, requestSource: ImageKnifeRequestSource) => { + showPixelMap: (version: number, pixelMap: PixelMap | string,size:Size, requestSource: ImageKnifeRequestSource) => { if (version !== this.componentVersion) { return //针对reuse场景,不显示历史图片 } this.pixelMap = pixelMap - if (typeof this.pixelMap !== 'string' && this.imageKnifeOption.objectFit === ImageFit.Auto) { //针对静态图高度自适应 - let info = await this.pixelMap.getImageInfo() - this.adaptiveWidth = this.currentWidth - this.adaptiveHeight = info.size.height * this.currentWidth / info.size.width + if (typeof this.pixelMap !== 'string') { + if (this.imageKnifeOption.objectFit === ImageFit.Auto) { + this.adaptiveWidth = this.currentWidth + this.adaptiveHeight = size.height * this.currentWidth / size.width + } } if (requestSource == ImageKnifeRequestSource.SRC) { @@ -165,4 +162,8 @@ export struct ImageKnifeComponent { return this.request } +} + +interface KeyCanvas { + keyId: string } \ No newline at end of file diff --git a/library/src/main/ets/downsampling/BaseDownsampling.ets b/library/src/main/ets/downsampling/BaseDownsampling.ets index 439a1cb..b7db695 100644 --- a/library/src/main/ets/downsampling/BaseDownsampling.ets +++ b/library/src/main/ets/downsampling/BaseDownsampling.ets @@ -1,21 +1,19 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { DownsampleStrategy } from './DownsampleStartegy'; -import { SampleSizeRounding } from './DownsampleUtils'; - export interface BaseDownsampling { getName(): string diff --git a/library/src/main/ets/downsampling/DownsampleStartegy.ets b/library/src/main/ets/downsampling/DownsampleStartegy.ets index 5e95a19..59cd7fb 100644 --- a/library/src/main/ets/downsampling/DownsampleStartegy.ets +++ b/library/src/main/ets/downsampling/DownsampleStartegy.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -17,7 +17,7 @@ import { getScale, highestOneBit, round, SampleSizeRounding } from './Downsample export class FitCenter implements BaseDownsampling { getName() { - return "FitCenter" + return 'FitCenter' } getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number, @@ -46,7 +46,7 @@ export class FitCenter implements BaseDownsampling { export class AtLeast implements BaseDownsampling { getName() { - return "AtLeast" + return 'AtLeast' } getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { @@ -67,7 +67,7 @@ export class AtLeast implements BaseDownsampling { export class AtMost implements BaseDownsampling { getName() { - return "AtMost" + return 'AtMost' } @@ -96,7 +96,7 @@ export class AtMost implements BaseDownsampling { 然后再更据原图的缩放比去适配另一边*/ export class CenterInside implements BaseDownsampling { getName() { - return "CenterInside" + return 'CenterInside' } getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number, downsampType: DownsampleStrategy @@ -107,7 +107,7 @@ export class CenterInside implements BaseDownsampling { } //将整型的缩放因子转换为2的次幂采样大小 let scaleFactor = this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight, - downsampType) == SampleSizeRounding.QUALITY ? + downsampType) == SampleSizeRounding.QUALITY ? Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height))) : Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height))) if (this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) diff --git a/library/src/main/ets/downsampling/Downsampler.ets b/library/src/main/ets/downsampling/Downsampler.ets index 328e228..a96f394 100644 --- a/library/src/main/ets/downsampling/Downsampler.ets +++ b/library/src/main/ets/downsampling/Downsampler.ets @@ -36,12 +36,12 @@ export class Downsampler { let scaleFactor: number = downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);//缩放比 //基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸 - if (typeValue === "png") { + if (typeValue === 'png') { return { width: Math.floor(sourceWidth / scaleFactor), height: Math.floor(sourceHeight / scaleFactor) } - } else if (typeValue === "webp") { + } else if (typeValue === 'webp') { return { width: Math.round(sourceWidth / scaleFactor), height: Math.round(sourceHeight / scaleFactor) @@ -70,4 +70,4 @@ export class Downsampler { throw new Error('Unsupported downsampling strategy'); } } -} +} \ No newline at end of file diff --git a/library/src/main/ets/key/DefaultEngineKey.ets b/library/src/main/ets/key/DefaultEngineKey.ets index 12f010f..d15d370 100644 --- a/library/src/main/ets/key/DefaultEngineKey.ets +++ b/library/src/main/ets/key/DefaultEngineKey.ets @@ -24,16 +24,16 @@ export class DefaultEngineKey implements IEngineKey { // 生成内存缓存key generateMemoryKey(loadSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource, imageKnifeOption: ImageKnifeOption,isAnimator?: boolean, width?: number, height?: number): string { - let key = (isAnimator == true ? "Animator=" : "loadSrc==") + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";" + let key = (isAnimator == true ? 'Animator=' : 'loadSrc==') + (typeof loadSrc == 'string' ? loadSrc : JSON.stringify(loadSrc)) + ';' if (requestSource === ImageKnifeRequestSource.SRC) { - if (imageKnifeOption.signature !== undefined && imageKnifeOption.signature !== "") { - key += "signature=" + imageKnifeOption.signature + ";" + if (imageKnifeOption.signature !== undefined && imageKnifeOption.signature !== '') { + key += 'signature=' + imageKnifeOption.signature + ';' } if (imageKnifeOption.transformation) { - key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";" + key += 'transformation=' + this.getTransformation(imageKnifeOption.transformation) + ';' } if ((imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE && imageKnifeOption.downsampleOf !== undefined)) { - key += "downsampleOf" + imageKnifeOption.downsampleOf +"width="+width+"height="+ height + key += 'downsampleOf' + imageKnifeOption.downsampleOf + 'width=' + width + 'height=' + height } } return key @@ -41,9 +41,9 @@ export class DefaultEngineKey implements IEngineKey { // 生成文件缓存key generateFileKey(loadSrc: string | PixelMap | Resource, signature?: string,isAnimator?: boolean): string { - let src = (isAnimator == true ? "Animator=" : "loadSrc==") + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";" - if (signature !== undefined && signature !== "") { - src += "signature=" + signature + ";" + let src = (isAnimator == true ? 'Animator=' : 'loadSrc==') + (typeof loadSrc == 'string' ? loadSrc : JSON.stringify(loadSrc)) + ';' + if (signature !== undefined && signature !== '') { + src += 'signature=' + signature + ';' } return SparkMD5.hashBinary(src) } diff --git a/library/src/main/ets/model/ImageKnifeData.ets b/library/src/main/ets/model/ImageKnifeData.ets index 8fb3b61..6d65078 100644 --- a/library/src/main/ets/model/ImageKnifeData.ets +++ b/library/src/main/ets/model/ImageKnifeData.ets @@ -21,12 +21,53 @@ import { Size } from '@kit.ArkUI' import { DownsampleStrategy } from '../downsampling/DownsampleStartegy' export interface ImageKnifeData { - source: PixelMap | string, - imageWidth: number, + source: PixelMap | string, // url + imageWidth: number, // 原始宽高大小 imageHeight: number, + bufSize?: number, // 图片的字节数 type?:string, imageAnimator?: Array + frameCount ?: number // 帧 + decodeImages?: Array //Image组件或者ImageAnimator组件可以加载一张或者多张 + timeInfo?: TimeInfo // 加载图片的各个时间点 + errorInfo?: ErrorInfo // 错误 } + +/** + * 解码后的图片的size + */ +export interface DecodeImageInfo { + contentWidth ?: number // 解码后宽高 + contentHeight?: number + contentSize ?: number // 大小 +} + +/** + * 加载的错误信息 + */ +export interface ErrorInfo { + phase: string, //图片加载阶段信息,如:网络加载阶段,缓存获取阶段及其解码阶段等 + code: number, + httpCode?: number +} + +/** + * load检查时间点 + */ +export interface TimeInfo { + requestStartTime?: number, + requestEndTime?: number, + requestCancelTime?: number, + memoryCheckStartTime?: number, + memoryCheckEndTime?: number, + diskCheckStartTime?: number, + diskCheckEndTime?: number, + netRequestStartTime?: number, + netRequestEndTime?: number, + decodeStartTime?: number, + decodeEndTime?: number, +} + /** * onComplete成功回调 */ @@ -79,7 +120,8 @@ export interface RequestJobResult { size?:Size, type?: string, pixelMapList?:Array, - delayList?: Array + delayList?: Array, + imageKnifeData?: ImageKnifeData, } /** @@ -92,7 +134,7 @@ export interface RequestJobRequest { allHeaders: Map, componentWidth: number, componentHeight: number, - customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise, + customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise, onlyRetrieveFromCache?: boolean requestSource: ImageKnifeRequestSource transformation?: PixelMapTransformation @@ -104,7 +146,8 @@ export interface RequestJobRequest { fileCacheFolder: string, isAnimator?: boolean, moduleName?:string, - resName?: string, + resName?: string + caPath?: string, targetWidth: number targetHeight: number downsampType: DownsampleStrategy diff --git a/library/src/main/ets/model/ImageKnifeOption.ets b/library/src/main/ets/model/ImageKnifeOption.ets index 4e42b00..9e9b100 100644 --- a/library/src/main/ets/model/ImageKnifeOption.ets +++ b/library/src/main/ets/model/ImageKnifeOption.ets @@ -17,101 +17,57 @@ import common from '@ohos.app.ability.common' import { CacheStrategy, ImageKnifeData,EventImage } from './ImageKnifeData'; import { PixelMapTransformation } from '../transform/PixelMapTransformation'; import { drawing } from '@kit.ArkGraphics2D'; +import { ImageKnifeRequest } from './ImageKnifeRequest'; import { DownsampleStrategy } from '../downsampling/DownsampleStartegy'; export interface HeaderOptions { key: string; value: Object; } -interface AnimatorType { - state?: AnimationStatus - iterations?: number - reverse?: boolean - onStart?:()=>void - onFinish?:()=>void - onPause?:()=>void - onCancel?:()=>void - onRepeat?:()=>void -} -@ObservedV2 + +@Observed export class AnimatorOption { - @Trace + @Track state?: AnimationStatus = AnimationStatus.Running - @Trace + @Track iterations?: number = -1 - @Trace + @Track reverse?: boolean = false - @Trace + @Track onStart?:()=>void - @Trace + @Track onFinish?:()=>void - @Trace + @Track onPause?:()=>void - @Trace + @Track onCancel?:()=>void - @Trace + @Track onRepeat?:()=>void - constructor(option?:AnimatorType) { - this.state = option?.state - this.iterations = option?.iterations - this.reverse = option?.reverse - this.onStart = option?.onStart - this.onFinish = option?.onFinish - this.onPause = option?.onPause - this.onCancel = option?.onCancel - this.onRepeat = option?.onRepeat - } } + interface ImageOption { - // 主图资源 - loadSrc: string | PixelMap | Resource - // 占位图 - placeholderSrc?: string | PixelMap | Resource - // 失败占位图 - errorholderSrc?: string | PixelMap | Resource - headerOption?: Array; - // 自定义缓存关键字 - signature?: string - // 主图填充效果 - objectFit?: ImageFit - // 占位图填充效果 - placeholderObjectFit?: ImageFit - // 错误图填充效果 - errorholderObjectFit?: ImageFit - customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise - border?: BorderOptions - // 缓存策略 - writeCacheStrategy?: CacheStrategy - // 仅使用缓存加载数据 - onlyRetrieveFromCache?: boolean; - priority?: taskpool.Priority - context?: common.UIAbilityContext; - progressListener?: (progress: number) => void; - transformation?: PixelMapTransformation - onLoadListener?: OnLoadCallBack | undefined; - onComplete?:(event:EventImage | undefined) => void - drawingColorFilter?: ColorFilter | drawing.ColorFilter - downsampleOf?: DownsampleStrategy + // 自定义证书路径 + caPath?: string, } -@ObservedV2 +@Observed export class ImageKnifeOption { // 主图资源 - @Trace loadSrc: string | PixelMap | Resource = ""; + loadSrc: string | PixelMap | Resource = ''; // 占位图 placeholderSrc?: string | PixelMap | Resource; // 失败占位图 errorholderSrc?: string | PixelMap | Resource; headerOption?: Array; // 自定义缓存关键字 - @Trace signature?: string; + signature?: string; // 主图填充效果 - @Trace objectFit?: ImageFit + objectFit?: ImageFit // 占位图填充效果 placeholderObjectFit?: ImageFit // 错误图填充效果 errorholderObjectFit?: ImageFit - customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise - @Trace border?: BorderOptions + customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise + border?: BorderOptions // 缓存策略 writeCacheStrategy?: CacheStrategy // 仅使用缓存加载数据 @@ -119,33 +75,15 @@ export class ImageKnifeOption { priority?: taskpool.Priority = taskpool.Priority.LOW context?: common.UIAbilityContext; progressListener?: (progress: number) => void; - @Trace transformation?: PixelMapTransformation + transformation?: PixelMapTransformation onLoadListener?: OnLoadCallBack | undefined; onComplete?:(event:EventImage | undefined) => void drawingColorFilter?: ColorFilter | drawing.ColorFilter - // 下采样 - @Trace downsampleOf: DownsampleStrategy = DownsampleStrategy.NONE - constructor(option?:ImageOption) { - this.loadSrc = option?.loadSrc == undefined ? "" : option?.loadSrc - this.placeholderSrc = option?.placeholderSrc - this.errorholderSrc = option?.errorholderSrc - this.headerOption = option?.headerOption - this.signature = option?.signature - this.objectFit = option?.objectFit - this.placeholderObjectFit = option?.placeholderObjectFit - this.errorholderObjectFit = option?.errorholderObjectFit - this.customGetImage = option?.customGetImage - this.border = option?.border - this.writeCacheStrategy = option?.writeCacheStrategy - this.onlyRetrieveFromCache = option?.onlyRetrieveFromCache - this.priority = option?.priority - this.context = option?.context - this.progressListener = option?.progressListener - this.transformation = option?.transformation - this.onLoadListener = option?.onLoadListener - this.onComplete = option?.onComplete - this.drawingColorFilter = option?.drawingColorFilter - this.downsampleOf = option?.downsampleOf==undefined?DownsampleStrategy.NONE:option?.downsampleOf + downsampleOf?: DownsampleStrategy // 降采样 + // 自定义证书路径 + caPath?: string + constructor() { + } } @@ -154,13 +92,13 @@ export class ImageKnifeOption { */ export interface OnLoadCallBack { // 请求开始 - onLoadStart?: () => void; + onLoadStart?: (request?: ImageKnifeRequest) => void; // 请求成功 - onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData) => void; + onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData, request?: ImageKnifeRequest) => void; // 请求结束 - onLoadFailed?: (err: string) => void; + onLoadFailed?: (err: string, request?: ImageKnifeRequest) => void; // 请求取消 - onLoadCancel?: (reason: string) => void; + onLoadCancel?: (reason: string, request?: ImageKnifeRequest) => void; } \ No newline at end of file diff --git a/library/src/main/ets/model/ImageKnifeRequest.ets b/library/src/main/ets/model/ImageKnifeRequest.ets index 530b707..6e5db4e 100644 --- a/library/src/main/ets/model/ImageKnifeRequest.ets +++ b/library/src/main/ets/model/ImageKnifeRequest.ets @@ -14,8 +14,7 @@ */ import { ImageKnifeOption } from './ImageKnifeOption'; import common from '@ohos.app.ability.common'; -import { ImageKnifeRequestSource } from './ImageKnifeData'; -import { DownsampleStrategy } from '../downsampling/DownsampleStartegy'; +import { ImageKnifeData, ImageKnifeRequestSource } from './ImageKnifeData'; export class ImageKnifeRequest { @@ -28,22 +27,19 @@ export class ImageKnifeRequest { ImageKnifeRequestCallback: ImageKnifeRequestCallback componentVersion: number = 0 headers: Map = new Map() - downsampType?: DownsampleStrategy + private imageCallBackData: ImageKnifeData | undefined = undefined; constructor(option: ImageKnifeOption, uIAbilityContext: common.UIAbilityContext, width: number, height: number, version: number, - ImageKnifeRequestCallback: ImageKnifeRequestCallback, - downsampType?: DownsampleStrategy - ) { + ImageKnifeRequestCallback: ImageKnifeRequestCallback) { this.imageKnifeOption = option this.context = uIAbilityContext this.componentWidth = width this.componentHeight = height this.componentVersion = version this.ImageKnifeRequestCallback = ImageKnifeRequestCallback - this.downsampType = downsampType } // RequestOption调用header对于的方法 addHeader(key: string, value: Object) { @@ -58,6 +54,14 @@ export class ImageKnifeRequest { } }) } + + setImageKnifeData(data: ImageKnifeData) { + this.imageCallBackData = data; + } + + getImageKnifeData(): ImageKnifeData | undefined { + return this.imageCallBackData + } } export enum ImageKnifeRequestState { @@ -69,5 +73,5 @@ export enum ImageKnifeRequestState { export interface ImageKnifeRequestCallback { - showPixelMap: (version: number, pixelMap: PixelMap | string , requestSource: ImageKnifeRequestSource,imageAnimator?: Array) => void; + showPixelMap: (version: number, pixelMap: PixelMap | string ,size: Size, requestSource: ImageKnifeRequestSource,imageAnimator?: Array) => void; } diff --git a/library/src/main/ets/queue/DefaultJobQueue.ets b/library/src/main/ets/queue/DefaultJobQueue.ets index 53f3d2a..5a4c1f7 100644 --- a/library/src/main/ets/queue/DefaultJobQueue.ets +++ b/library/src/main/ets/queue/DefaultJobQueue.ets @@ -18,9 +18,9 @@ import Queue from '@ohos.util.Queue'; import { taskpool,Stack } from '@kit.ArkTS'; export class DefaultJobQueue implements IJobQueue { - highQueue: Stack = new Stack(); - normalQueue: Stack = new Stack(); - lowQueue: Stack = new Stack(); + highQueue: Queue = new Queue(); + normalQueue: Queue = new Queue(); + lowQueue: Queue = new Queue(); getQueueLength(): number { return this.highQueue.length + this.normalQueue.length + this.lowQueue.length @@ -28,11 +28,11 @@ export class DefaultJobQueue implements IJobQueue { add(request: ImageKnifeRequest): void { if (request.imageKnifeOption.priority === undefined || request.imageKnifeOption.priority === taskpool.Priority.MEDIUM) { - this.normalQueue.push(request) + this.normalQueue.add(request) } else if (request.imageKnifeOption.priority === taskpool.Priority.HIGH) { - this.highQueue.push(request) + this.highQueue.add(request) } else { - this.lowQueue.push(request) + this.lowQueue.add(request) } } diff --git a/library/src/main/ets/transform/CropCircleTransformation.ets b/library/src/main/ets/transform/CropCircleTransformation.ets index 707ecbf..4b69da2 100644 --- a/library/src/main/ets/transform/CropCircleTransformation.ets +++ b/library/src/main/ets/transform/CropCircleTransformation.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -44,7 +44,7 @@ export class CropCircleTransformation extends PixelMapTransformation { height: imageInfo.size.height }; if (!size) { - console.error("CropCircleTransformation The image size does not exist."); + console.error('CropCircleTransformation The image size does not exist.'); return data; } let height: number = size.height; diff --git a/library/src/main/ets/transform/CropCircleWithBorderTransformation.ets b/library/src/main/ets/transform/CropCircleWithBorderTransformation.ets index bad7336..e7d578d 100644 --- a/library/src/main/ets/transform/CropCircleWithBorderTransformation.ets +++ b/library/src/main/ets/transform/CropCircleWithBorderTransformation.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -67,7 +67,7 @@ export class CropCircleWithBorderTransformation extends PixelMapTransformation { height: imageInfo.size.height }; if (!size) { - console.error("CropCircleWithBorderTransformation The image size does not exist."); + console.error('CropCircleWithBorderTransformation The image size does not exist.'); return pixelMap; } let height: number = size.height; diff --git a/library/src/main/ets/transform/CropSquareTransformation.ets b/library/src/main/ets/transform/CropSquareTransformation.ets index f939845..35cb016 100644 --- a/library/src/main/ets/transform/CropSquareTransformation.ets +++ b/library/src/main/ets/transform/CropSquareTransformation.ets @@ -32,7 +32,7 @@ export class CropSquareTransformation extends PixelMapTransformation { height: imageInfo.size.height }; if (!size) { - console.error("CropSquareTransformation The image size does not exist."); + console.error('CropSquareTransformation The image size does not exist.'); return toTransform; } let pixelMapWidth: number = size.width; diff --git a/library/src/main/ets/transform/CropTransformation.ets b/library/src/main/ets/transform/CropTransformation.ets index 1d63651..5337ecc 100644 --- a/library/src/main/ets/transform/CropTransformation.ets +++ b/library/src/main/ets/transform/CropTransformation.ets @@ -33,7 +33,7 @@ export class CropTransformation extends PixelMapTransformation { } getName(): string { - return this.constructor.name + ";mWidth:" + this.mWidth + ";mHeight:" + this.mHeight + ";mCropType:" + this.mCropType; + return this.constructor.name + ';mWidth:' + this.mWidth + ';mHeight:' + this.mHeight + ';mCropType:' + this.mCropType; } async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { @@ -43,7 +43,7 @@ export class CropTransformation extends PixelMapTransformation { height: imageInfo.size.height }; if (!size) { - console.error("CropTransformation The image size does not exist."); + console.error('CropTransformation The image size does not exist.'); return toTransform; } let pixelMapWidth: number = size.width; diff --git a/library/src/main/ets/transform/KuwaharaTransformation.ets b/library/src/main/ets/transform/KuwaharaTransformation.ets index 4baf79b..3157724 100644 --- a/library/src/main/ets/transform/KuwaharaTransformation.ets +++ b/library/src/main/ets/transform/KuwaharaTransformation.ets @@ -35,7 +35,7 @@ export class KuwaharaTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("KuwaharaTransformation The image size does not exist."); + console.error('KuwaharaTransformation The image size does not exist.'); return toTransform; } return await this.kuwaharaGpu(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/MaskTransformation.ets b/library/src/main/ets/transform/MaskTransformation.ets index a715cf1..8293e25 100644 --- a/library/src/main/ets/transform/MaskTransformation.ets +++ b/library/src/main/ets/transform/MaskTransformation.ets @@ -45,7 +45,7 @@ export class MaskTransformation extends PixelMapTransformation { height: imageInfo.size.height }; if (!size) { - console.error("MaskTransformation The image size does not exist."); + console.error('MaskTransformation The image size does not exist.'); return toTransform; } let pixelMapWidth: number = size.width; @@ -62,17 +62,17 @@ export class MaskTransformation extends PixelMapTransformation { private async openInternal(context: Context, bitmap: PixelMap, width: number, height: number): Promise { if (context == undefined) { - console.error("MaskTransformation openInternal the context is undefined."); + console.error('MaskTransformation openInternal the context is undefined.'); return bitmap; } let moduleContext = context.createModuleContext(this.mResourceModuleName); if (moduleContext == undefined) { - console.error("MaskTransformation openInternal the moduleContext is undefined."); + console.error('MaskTransformation openInternal the moduleContext is undefined.'); return bitmap; } let resourceManager = moduleContext.resourceManager as resourceManager.ResourceManager; if (resourceManager == undefined) { - console.error("MaskTransformation openInternal the resourceManager is undefined."); + console.error('MaskTransformation openInternal the resourceManager is undefined.'); return bitmap; } let array: Uint8Array = await resourceManager.getMediaContent(this.mResourceId); @@ -96,7 +96,7 @@ export class MaskTransformation extends PixelMapTransformation { height: imageInfo.size.height }; if (!size) { - console.error("MaskTransformation mask the image size does not exist."); + console.error('MaskTransformation mask the image size does not exist.'); return bitmap; } let width = size.width; @@ -133,7 +133,7 @@ export class MaskTransformation extends PixelMapTransformation { height: imageInfoMask.size.height }; if (!sizeMask) { - console.error("MaskTransformation mask the sizeMask size does not exist."); + console.error('MaskTransformation mask the sizeMask size does not exist.'); return bitmap; } let widthMask = sizeMask.width; diff --git a/library/src/main/ets/transform/MultiTransTransformation.ets b/library/src/main/ets/transform/MultiTransTransformation.ets index 459afbc..b032a1d 100644 --- a/library/src/main/ets/transform/MultiTransTransformation.ets +++ b/library/src/main/ets/transform/MultiTransTransformation.ets @@ -37,9 +37,9 @@ export class MultiTransTransformation extends PixelMapTransformation { } getName(): string { - let res: string = "" + let res: string = '' this.transformations.forEach((transformation) => { - res += transformation.getName() + "&" + res += transformation.getName() + '&' }) return res } diff --git a/library/src/main/ets/transform/PixelationTransformation.ets b/library/src/main/ets/transform/PixelationTransformation.ets index 2a32d78..d226e06 100644 --- a/library/src/main/ets/transform/PixelationTransformation.ets +++ b/library/src/main/ets/transform/PixelationTransformation.ets @@ -39,7 +39,7 @@ export class PixelationTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("PixelationTransformation The image size does not exist."); + console.error('PixelationTransformation The image size does not exist.'); return toTransform; } return await this.pixelGPU(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/SepiaTransformation.ets b/library/src/main/ets/transform/SepiaTransformation.ets index 153d69d..728c079 100644 --- a/library/src/main/ets/transform/SepiaTransformation.ets +++ b/library/src/main/ets/transform/SepiaTransformation.ets @@ -28,7 +28,7 @@ export class SepiaTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("SepiaTransformation The image size does not exist."); + console.error('SepiaTransformation The image size does not exist.'); return toTransform; } return await this.sepiaGPU(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/SketchTransformation.ets b/library/src/main/ets/transform/SketchTransformation.ets index 2f8933d..91a9d05 100644 --- a/library/src/main/ets/transform/SketchTransformation.ets +++ b/library/src/main/ets/transform/SketchTransformation.ets @@ -28,7 +28,7 @@ export class SketchTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("SketchTransformation The image size does not exist."); + console.error('SketchTransformation The image size does not exist.'); return toTransform; } return await this.sketchGPU(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/SwirlTransformation.ets b/library/src/main/ets/transform/SwirlTransformation.ets index 1cebc74..02b7d09 100644 --- a/library/src/main/ets/transform/SwirlTransformation.ets +++ b/library/src/main/ets/transform/SwirlTransformation.ets @@ -50,7 +50,7 @@ export class SwirlTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("SwirlTransformation The image size does not exist."); + console.error('SwirlTransformation The image size does not exist.'); return toTransform; } return await this.swirlGPU(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/ToonTransformation.ets b/library/src/main/ets/transform/ToonTransformation.ets index 8b73343..89bd085 100644 --- a/library/src/main/ets/transform/ToonTransformation.ets +++ b/library/src/main/ets/transform/ToonTransformation.ets @@ -41,7 +41,7 @@ export class ToonTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("ToonTransformation The image size does not exist."); + console.error('ToonTransformation The image size does not exist.'); return toTransform; } return await this.toonGPU(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/VignetterTransformation.ets b/library/src/main/ets/transform/VignetterTransformation.ets index a8c7691..f750a66 100644 --- a/library/src/main/ets/transform/VignetterTransformation.ets +++ b/library/src/main/ets/transform/VignetterTransformation.ets @@ -54,7 +54,7 @@ export class VignetterTransformation extends PixelMapTransformation { async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise { let imageInfo: image.ImageInfo = await toTransform.getImageInfo(); if (!imageInfo.size) { - console.error("VignetterTransformation The image size does not exist."); + console.error('VignetterTransformation The image size does not exist.'); return toTransform; } return await this.swirlGPU(toTransform, imageInfo.size.width, imageInfo.size.height); diff --git a/library/src/main/ets/transform/entry/PixelEntry.ets b/library/src/main/ets/transform/entry/PixelEntry.ets index 4a0205a..f16783a 100644 --- a/library/src/main/ets/transform/entry/PixelEntry.ets +++ b/library/src/main/ets/transform/entry/PixelEntry.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -21,6 +21,6 @@ export class PixelEntry { pixel: number = 0; public toString(): string { - return "PixelEntry a:" + this.a + ";b:" + this.b + ";r:" + this.r + ";g:" + this.g + ";f:" + this.f; + return 'PixelEntry a:' + this.a + ';b:' + this.b + ';r:' + this.r + ';g:' + this.g + ';f:' + this.f; } } \ No newline at end of file diff --git a/library/src/main/ets/utils/CalculatePixelUtils.ets b/library/src/main/ets/utils/CalculatePixelUtils.ets index 3bf1568..34abc04 100644 --- a/library/src/main/ets/utils/CalculatePixelUtils.ets +++ b/library/src/main/ets/utils/CalculatePixelUtils.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. diff --git a/library/src/main/ets/utils/ColorUtils.ets b/library/src/main/ets/utils/ColorUtils.ets index 5c1ee2e..4437557 100644 --- a/library/src/main/ets/utils/ColorUtils.ets +++ b/library/src/main/ets/utils/ColorUtils.ets @@ -1,13 +1,13 @@ /* * Copyright (C) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. diff --git a/library/src/main/ets/utils/Constants.ets b/library/src/main/ets/utils/Constants.ets index d187451..98dbd4e 100644 --- a/library/src/main/ets/utils/Constants.ets +++ b/library/src/main/ets/utils/Constants.ets @@ -13,5 +13,62 @@ * limitations under the License. */ export class Constants { - public static PROGRESS_EMITTER: string = "progressEmitter" + public static PROGRESS_EMITTER: string = 'progressEmitter' + public static CALLBACK_EMITTER: string = 'callBackEmitter' +} + +/** + * 图片加载的code + */ +export enum LoadPixelMapCode { + // createImageSource error code + IMAGE_SOURCE_ERROR_CODE = 100001, + // createPixelMap error code + IMAGE_DECODE_ERROR_CODE = 100002, + //ImageKnifeAnimatorComponent组件仅支持动态图 code + IMAGE_FORMAT_ERROR_CODE = 100003, + //load failed code + IMAGE_LOAD_FAILED_CODE = 100004, + //自定义下载失败 code + IMAGE_CUSTOM_LOAD_FAILED_CODE = 100005, + // http请求失败 code + IMAGE_HTTPS_LOAD_FAILED_CODE = 100006, + //设置onlyRetrieveFromCache 导致的加载失败的code + IMAGE_RETRIEVE_CACHE_CODE = 100007, + //加载共享图片失败code + IMAGE_LOAD_SHARE_FILE_FAILED_CODE = 100008, + //加载本地文件图片失败code + IMAGE_LOAD_LOCAL_FILE_FAILED_CODE = 100009, + // 取消请求加载code + IMAGE_LOAD_CANCEL_FAILED_CODE = 1000010, + // 解析图片格式阶段 + IMAGE_PARSE_FORMAT_FAILED_CODE = 1000011 +} + +/** + * 图片加载的各个阶段 + */ +export enum LoadPhase { + // 图片加载阶段 + PHASE_LOAD = 'load', + // 网络请求下载阶段 + PHASE_NET = 'net', + //获取图片格式阶段 + PHASE_GET_FORMAT = 'parse_format', + //自定义下载阶段 customGetImage + PHASE_CUSTOM_LOAD = 'customGetImage', + // createPixelMap 阶段 + PHASE_CREATE_SOURCE = 'createImageSource', + //createPixelMap 阶段 + PHASE_CREATE_PIXEL_MAP = 'createPixelMap', + //请求队列排队阶段 + PHASE_THREAD_QUEUE = 'thread_queue', + //图片解析阶段 + PHASE_PARSE_IAMGE = 'parseImage', + //加载解析datashare:// 或者file:// 阶段 + PHASE_SHARE_FILE = 'datashare_or_file', + //加载解析本地文件阶段 + PHASE_LOCAL_FILE = 'load_local_file', + //图片加载解析完成,即将显示的阶段 + PHASE_WILL_SHOW = 'will_show', } \ No newline at end of file diff --git a/library/src/main/ets/utils/FileTypeUtil.ets b/library/src/main/ets/utils/FileTypeUtil.ets index 7627162..60d7f8b 100644 --- a/library/src/main/ets/utils/FileTypeUtil.ets +++ b/library/src/main/ets/utils/FileTypeUtil.ets @@ -80,7 +80,7 @@ export class FileTypeUtil { return false; // 文件长度不足,无法匹配魔数 } - for (let i = fileType == "heic" ? 4 : 0; i < signature.length; i++) { + for (let i = fileType == 'heic' ? 4 : 0; i < signature.length; i++) { if (fileData[i] !== signature[i]) { return false; // 魔数不匹配 } diff --git a/library/src/main/ets/utils/FileUtils.ets b/library/src/main/ets/utils/FileUtils.ets index 5f41dd1..b458d94 100644 --- a/library/src/main/ets/utils/FileUtils.ets +++ b/library/src/main/ets/utils/FileUtils.ets @@ -47,7 +47,7 @@ export class FileUtils { } return true } catch (err) { - LogUtil.error("FileUtils deleteFileSync failed: err msg=" + err.message + " err code=" + err.code); + LogUtil.error('FileUtils deleteFileSync failed: err msg=' + err.message + ' err code=' + err.code); return false } } @@ -63,7 +63,7 @@ export class FileUtils { try { await fs.unlink(path) } catch (err) { - LogUtil.error("FileUtils deleteFile failed: err msg=" + err.message + " err code=" + err.code); + LogUtil.error('FileUtils deleteFile failed: err msg=' + err.message + ' err code=' + err.code); } } @@ -82,7 +82,7 @@ export class FileUtils { return true } catch (err) { - LogUtil.error("FileUtils writeDataSync failed: err msg=" + err.message + " err code=" + err.code); + LogUtil.error('FileUtils writeDataSync failed: err msg=' + err.message + ' err code=' + err.code); return false } } @@ -102,7 +102,7 @@ export class FileUtils { return true } catch (err) { - LogUtil.error("FileUtils writeData failed: err msg=" + err.message + " err code=" + err.code); + LogUtil.error('FileUtils writeData failed: err msg=' + err.message + ' err code=' + err.code); return false } } @@ -122,7 +122,7 @@ export class FileUtils { } } catch (error) { let err: BusinessError = error as BusinessError; - LogUtil.error("FileUtils exist failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils exist failed with error message: ' + err.message + ', error code: ' + err.code); } return false } @@ -137,7 +137,7 @@ export class FileUtils { let stat = fs.statSync(path) return stat.size } catch (e) { - LogUtil.error("FileUtils getFileSize e " + e) + LogUtil.error('FileUtils getFileSize e ' + e) return -1 } } @@ -159,7 +159,7 @@ export class FileUtils { } } catch (error) { let err: BusinessError = error as BusinessError; - LogUtil.error("FileUtils readFileSync failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils readFileSync failed with error message: ' + err.message + ', error code: ' + err.code); } return undefined } @@ -176,10 +176,11 @@ export class FileUtils { let length = stat.size; let buf = new ArrayBuffer(length); await fs.read(fd, buf); + await fs.close(fd) return buf } catch (error) { let err: BusinessError = error as BusinessError; - LogUtil.error("FileUtils readFile failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils readFile failed with error message: ' + err.message + ', error code: ' + err.code); } return undefined } @@ -210,7 +211,7 @@ export class FileUtils { } } } catch (e) { - LogUtil.log("FileUtils createFolder err : " + e) + LogUtil.log('FileUtils createFolder err : ' + e) } } @@ -224,7 +225,7 @@ export class FileUtils { return true } catch (error) { let err: BusinessError = error as BusinessError; - LogUtil.error("FileUtils createFolder failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils createFolder failed with error message: ' + err.message + ', error code: ' + err.code); } return false } @@ -245,7 +246,7 @@ export class FileUtils { } catch (error) { let err: BusinessError = error as BusinessError; - LogUtil.error("FileUtils existFolder failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils existFolder failed with error message: ' + err.message + ', error code: ' + err.code); } return false } @@ -258,7 +259,7 @@ export class FileUtils { fs.closeSync(fd) return true } catch (err) { - LogUtil.error("FileUtils writeFileSync failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils writeFileSync failed with error message: ' + err.message + ', error code: ' + err.code); } return false } @@ -267,7 +268,7 @@ export class FileUtils { try { return fs.listFileSync(path) } catch (err) { - LogUtil.error("FileUtils ListFileSync failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils ListFileSync failed with error message: ' + err.message + ', error code: ' + err.code); } return [] } @@ -276,7 +277,7 @@ export class FileUtils { try { return fs.listFile(path) } catch (err) { - LogUtil.error("FileUtils ListFile failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils ListFile failed with error message: ' + err.message + ', error code: ' + err.code); } return [] } @@ -285,7 +286,7 @@ export class FileUtils { try { return fs.statSync(path) } catch (err) { - LogUtil.error("FileUtils StatSync failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils StatSync failed with error message: ' + err.message + ', error code: ' + err.code); } return undefined } @@ -294,7 +295,7 @@ export class FileUtils { try { return fs.stat(path) } catch (err) { - LogUtil.error("FileUtils Stat failed with error message: " + err.message + ", error code: " + err.code); + LogUtil.error('FileUtils Stat failed with error message: ' + err.message + ', error code: ' + err.code); } return undefined } diff --git a/library/src/main/ets/utils/LogUtil.ets b/library/src/main/ets/utils/LogUtil.ets index d59f582..7c802a2 100644 --- a/library/src/main/ets/utils/LogUtil.ets +++ b/library/src/main/ets/utils/LogUtil.ets @@ -16,7 +16,7 @@ import { hilog } from '@kit.PerformanceAnalysisKit'; export class LogUtil { public static readonly DOMAIN: number = 0xD002220; - public static readonly TAG: string = "ImageKnife::"; + public static readonly TAG: string = 'ImageKnife::'; public static debug(message: string, ...args: Object[]) { hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args) diff --git a/sharedlibrary/Index.ets b/sharedlibrary/Index.ets index 5d74d4b..99a925e 100644 --- a/sharedlibrary/Index.ets +++ b/sharedlibrary/Index.ets @@ -24,6 +24,8 @@ export { ImageKnife } from '@ohos/imageknife' export { ImageKnifeOption,AnimatorOption } from '@ohos/imageknife' +export { DownsampleStrategy } from "@ohos/imageknife" + export { ImageKnifeRequest } from '@ohos/imageknife' export { FileUtils } from '@ohos/imageknife' diff --git a/sharedlibrary/src/main/ets/pages/Index.ets b/sharedlibrary/src/main/ets/pages/Index.ets index 92d223f..16eaada 100644 --- a/sharedlibrary/src/main/ets/pages/Index.ets +++ b/sharedlibrary/src/main/ets/pages/Index.ets @@ -14,14 +14,14 @@ */ import { ImageKnife , ImageKnifeComponent ,ImageKnifeOption } from "@ohos/imageknife" -@ComponentV2 +@Component export struct IndexComponent { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ + @State imageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon') - }) + } build() { Column() { - Button($r('app.string.Preload')).onClick((event: ClickEvent) => { + Button("preload").onClick((event: ClickEvent) => { ImageKnife.getInstance() .preLoadCache('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp') .then((data) => {