From 1b5aea1138251db4ee8ddcb90d14cfcfcc8bb8cc Mon Sep 17 00:00:00 2001 From: zhoulisheng1 Date: Thu, 16 Mar 2023 17:39:59 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD:?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E7=BC=93=E5=AD=98?= =?UTF-8?q?key=202.=E6=B7=BB=E5=8A=A0=E7=BC=93=E5=AD=98key=E4=B8=AD?= =?UTF-8?q?=E7=9A=84url=E9=9C=80=E8=A6=81=E5=89=94=E9=99=A4token=E7=9A=84?= =?UTF-8?q?=E6=BC=94=E7=A4=BA=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhoulisheng1 --- .../ets/entryability/CustomEngineKeyImpl.ets | 63 ++++++++++++++++ .../src/main/ets/entryability/EntryAbility.ts | 5 +- ...tCasePage.ets => CacheRuleChangedPage.ets} | 53 ++++++++++---- .../ets/pages/imageknifeTestCaseIndex.ets | 8 +-- .../resources/base/profile/main_pages.json | 2 +- imageknife/index.ets | 2 + .../ets/components/cache/key/EngineKey.ets | 72 ++++++------------- .../cache/key/EngineKeyFactories.ets | 39 ++++++---- .../cache/key/EngineKeyInterface.ets | 27 +++++++ .../ets/components/imageknife/ImageKnife.ets | 48 +++++++++++-- package.json | 2 + 11 files changed, 234 insertions(+), 87 deletions(-) create mode 100644 entry/src/main/ets/entryability/CustomEngineKeyImpl.ets rename entry/src/main/ets/pages/{frescoImageTestCasePage.ets => CacheRuleChangedPage.ets} (55%) create mode 100644 imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets diff --git a/entry/src/main/ets/entryability/CustomEngineKeyImpl.ets b/entry/src/main/ets/entryability/CustomEngineKeyImpl.ets new file mode 100644 index 0000000..a89aba9 --- /dev/null +++ b/entry/src/main/ets/entryability/CustomEngineKeyImpl.ets @@ -0,0 +1,63 @@ +import { EngineKeyInterface,EngineKeyFactories, RequestOption } from '@ohos/imageknife' + +export class CustomEngineKeyImpl implements EngineKeyInterface { + + redefineUrl:(loadSrc:string)=>string; + + addOtherInfo:string = "Version=1.0.0;" + + constructor() { + this.redefineUrl = this.urlNeedClearToken.bind(this); + } + // request只读 + generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean):string { + return EngineKeyFactories.createMemoryCacheKey(loadSrc,size,transformed,dontAnimate,this.redefineUrl,this.addOtherInfo); + } + + generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean):string { + return EngineKeyFactories.createTransformedDiskCacheKey(loadSrc,size,transformed,dontAnimate,this.redefineUrl,this.addOtherInfo); + } + + generateOriginalDiskCacheKey(loadSrc:string):string { + return EngineKeyFactories.createOriginalDiskCacheKey(loadSrc,this.redefineUrl,this.addOtherInfo); + } + + + // 需求场景: 请求图片可能 请求中存在token需要清除, 可以把输入的url清除token后作为key的一部分,这样token发生变化也能命中缓存。 + urlNeedClearToken(url:string):string { + if (this.isHttpRequest(url)) { + return this.clearToken(url) + } else { + return url; + } + } + + + isHttpRequest(loadSrc:string){ + if(typeof loadSrc == "string" && loadSrc.toLowerCase().startsWith("http")){ + return true; + } + return false; + } + + // 清除url里面中携带的token + clearToken(url:string):string{ + let retUrl = url.replace(this.findTokenParam(url),"") + return retUrl; + } + + // 网络图片加载 可能因为Token问题导致缓存失效 + findTokenParam(url: string): string { + let tokenParam = ""; + let tokenKeyIndex = url.indexOf("?token=") >= 0 ? url.indexOf("?token=") : url.indexOf("&token="); + if (tokenKeyIndex != -1) { + let nextAndIndex = url.indexOf("&", tokenKeyIndex + 1); + if (nextAndIndex != -1) { + tokenParam = url.substring(tokenKeyIndex + 1, nextAndIndex + 1); + } else { + tokenParam = url.substring(tokenKeyIndex); + } + } + return tokenParam; + } +} diff --git a/entry/src/main/ets/entryability/EntryAbility.ts b/entry/src/main/ets/entryability/EntryAbility.ts index 2243e00..5589925 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ts +++ b/entry/src/main/ets/entryability/EntryAbility.ts @@ -1,7 +1,8 @@ import UIAbility from '@ohos.app.ability.UIAbility'; import hilog from '@ohos.hilog'; import window from '@ohos.window'; -import { ImageKnife,ImageKnifeDrawFactory} from '@ohos/imageknife' +import { ImageKnife,ImageKnifeDrawFactory } from '@ohos/imageknife' +import { CustomEngineKeyImpl } from './CustomEngineKeyImpl' export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { @@ -9,6 +10,8 @@ export default class EntryAbility extends UIAbility { globalThis.ImageKnife = ImageKnife.with(this.context); // 全局配置网络加载进度条 globalThis.ImageKnife.setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5)) + // 全局配置缓存key + globalThis.ImageKnife.setEngineKeyImpl(new CustomEngineKeyImpl()) } onDestroy() { diff --git a/entry/src/main/ets/pages/frescoImageTestCasePage.ets b/entry/src/main/ets/pages/CacheRuleChangedPage.ets similarity index 55% rename from entry/src/main/ets/pages/frescoImageTestCasePage.ets rename to entry/src/main/ets/pages/CacheRuleChangedPage.ets index c12ee29..aac53dd 100644 --- a/entry/src/main/ets/pages/frescoImageTestCasePage.ets +++ b/entry/src/main/ets/pages/CacheRuleChangedPage.ets @@ -12,16 +12,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ImageKnifeComponent} from '@ohos/imageknife' -import {ImageKnifeOption} from '@ohos/imageknife' -import {RotateImageTransformation} from '@ohos/imageknife' -import {RoundedCornersTransformation} from '@ohos/imageknife' +import { + ImageKnifeComponent, + ImageKnifeOption, + RotateImageTransformation, + RoundedCornersTransformation +} from '@ohos/imageknife' @Entry @Component -struct FrescoImageTestCasePage { - - @State progresshint:string = "输出加载百分比回调信息" +struct CacheRuleChangedPage { + @State progresshint: string = "输出加载百分比回调信息" @State imageKnifeOption1: ImageKnifeOption = { loadSrc: "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83ericA1Mv66TwicuYOtbDMBcUhv1aa9RJBeAn9uURfcZD0AUGrJebAn1g2AjN0vb2E1XTET7fTuLBNmA/132", @@ -50,6 +51,14 @@ struct FrescoImageTestCasePage { { loadSrc: "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + displayProgress: true, + }; + @State imageKnifeOption5: ImageKnifeOption = + { + loadSrc: "https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp?mama=sdafsfasdfsdfsdaf&baba=sdfsafsafsd", + placeholderSrc: $r('app.media.icon_loading'), errorholderSrc: $r('app.media.icon_failed'), displayProgress: true, @@ -58,17 +67,35 @@ struct FrescoImageTestCasePage { build() { Scroll() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { -// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }) -// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }) -// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption3 }) + + Text('下图默认加载网络图片不带?token=').margin({top:20}) + Button('点击加载网络图片?token=').margin({top:5}).onClick(() => { + + this.imageKnifeOption4 = { + loadSrc: "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB?token=fsdafsfsafsafsdaf111111", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + displayProgress: true, + } + }) + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption4 }) .width(300) .height(300) -// Scroll() { -// Text(this.progresshint).fontSize(15) -// }.width(300).height(200) + Text('下图默认加载网络图片不带&token=').margin({top:20}) + Button('点击加载网络图片&token=').margin({top:5}).onClick(() => { + this.imageKnifeOption5 = { + loadSrc: "https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp?mama=sdafsfasdfsdfsdaf&token=fsdafsfsafsafsdaf111111&baba=sdfsafsafsd", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + displayProgress: true, + } + }) + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption5 }) + .width(300) + .height(300) } } .width('100%') diff --git a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets index 108abb5..f01d186 100644 --- a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets +++ b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets @@ -127,12 +127,12 @@ struct IndexFunctionDemo { }).margin({ top: 5, left: 3 }) }.width('100%').height(60).backgroundColor(Color.Pink) - Text("测试fresco").fontSize(15) + Text("测试缓存规则和重试").fontSize(15) Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Button("加载百分比") + Button("更改缓存规则") .onClick(() => { - console.log("加载百分比") - router.push({ uri: "pages/frescoImageTestCasePage" }); + console.log("更改缓存规则") + router.push({ uri: "pages/CacheRuleChangedPage" }); }).margin({ top: 5, left: 3 }) Button("重试Retry") .onClick(() => { diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 37dfa72..1d45314 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -1,7 +1,7 @@ { "src": [ "pages/index", - "pages/frescoImageTestCasePage", + "pages/CacheRuleChangedPage", "pages/frescoRetryTestCasePage", "pages/basicTestFeatureAbilityPage", "pages/basicTestFileIOPage", diff --git a/imageknife/index.ets b/imageknife/index.ets index b37f483..c4e36ac 100644 --- a/imageknife/index.ets +++ b/imageknife/index.ets @@ -27,6 +27,8 @@ export * from './src/main/ets/components/cache/diskstrategy/enum/AUTOMATIC' export * from './src/main/ets/components/cache/diskstrategy/enum/DATA' export * from './src/main/ets/components/cache/diskstrategy/enum/NONE' export * from './src/main/ets/components/cache/diskstrategy/enum/RESOURCE' +export * from './src/main/ets/components/cache/key/EngineKeyInterface' +export * from './src/main/ets/components/cache/key/EngineKeyFactories' /** * compress diff --git a/imageknife/src/main/ets/components/cache/key/EngineKey.ets b/imageknife/src/main/ets/components/cache/key/EngineKey.ets index be28a7c..1dce528 100644 --- a/imageknife/src/main/ets/components/cache/key/EngineKey.ets +++ b/imageknife/src/main/ets/components/cache/key/EngineKey.ets @@ -17,76 +17,50 @@ import {RequestOption} from '../../imageknife/RequestOption' import {BaseTransform} from '../../imageknife/transform/BaseTransform' export class EngineKey implements Key { - private request: RequestOption; - - constructor( - request - ) { - this.request = request; - } // 内存缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目 // 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图) - generateCacheKey(): string{ + public static generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{ - let loadSrc = JSON.stringify(this.request.loadSrc); - - let size = JSON.stringify(this.request.size); - - let transformationsStr; - if(this.request && this.request.transformations) { - for (let i = 0; i < this.request.transformations.length; i++) { - if (i == this.request.transformations.length - 1) { - transformationsStr += this.request.transformations[i].getName() + ""; - } else { - transformationsStr += this.request.transformations[i].getName() + ","; - } - } + if(redefine){ + loadSrc = redefine(loadSrc); } - let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag); - let key = "loadSrc=" + loadSrc + ";" + "size=" + size + ";" + - "transformations=" + transformationsStr + ";" + - "dontAnimateFlag=" + dontAnimateFlag + ";" - + "transformations=" + transformed + ";" + + "dontAnimateFlag=" + dontAnimate + ";" + if(otherInfo){ + key += otherInfo; + } return key; } // 磁盘缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目 // 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图) - generateResourceKey(): string{ - - let loadSrc = JSON.stringify(this.request.loadSrc); - - let size = JSON.stringify(this.request.size); - - let transformationsStr; - if(this.request && this.request.transformations) { - for (let i = 0; i < this.request.transformations.length; i++) { - if (i == this.request.transformations.length - 1) { - transformationsStr += this.request.transformations[i].getName() + ""; - } else { - transformationsStr += this.request.transformations[i].getName() + ","; - } - } + public static generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{ + if(redefine){ + loadSrc = redefine(loadSrc); } - - let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag); - let key = "loadSrc=" + loadSrc + ";" + "size=" + size + ";" + - "transformations=" + transformationsStr + ";" + - "dontAnimateFlag=" + dontAnimateFlag + ";" - + "transformations=" + transformed + ";" + + "dontAnimateFlag=" + dontAnimate + ";" + if(otherInfo){ + key += otherInfo; + } return key; } // 磁盘缓存 // 生成网络加载数据 原始数据存于磁盘的key - generateDataKey(): string{ - let loadSrc = JSON.stringify(this.request.loadSrc); + public static generateOriginalDiskCacheKey(loadSrc:string, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{ + if(redefine){ + loadSrc = redefine(loadSrc); + } let key = "loadSrc=" + loadSrc + ";" + if(otherInfo){ + key += otherInfo; + } return key; } diff --git a/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets b/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets index f81f0ce..1b30570 100644 --- a/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets +++ b/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets @@ -13,24 +13,39 @@ * limitations under the License. */ import {EngineKey} from '../key/EngineKey' +import {EngineKeyInterface} from '../key/EngineKeyInterface' +import {RequestOption} from '../../imageknife/RequestOption' -export class EngineKeyFactories { - buildCacheKey( - request) { - return new EngineKey(request).generateCacheKey(); +export class EngineKeyFactories implements EngineKeyInterface { + // 生成内存缓存 + generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) { + return EngineKey.generateMemoryCacheKey(loadSrc,size,transformed,dontAnimate); + } + // 生成原图变换后的图片的磁盘缓存 + generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) { + return EngineKey.generateTransformedDiskCacheKey(loadSrc,size,transformed,dontAnimate); + } + // 生成原图的磁盘缓存 + generateOriginalDiskCacheKey(loadSrc:string) { + return EngineKey.generateOriginalDiskCacheKey(loadSrc); } - buildDataKey( - request - ) { - return new EngineKey(request).generateDataKey() + public static createMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string{ + return EngineKey.generateMemoryCacheKey(loadSrc,size,transformed,dontAnimate,redefineUrl,addOtherInfo); } - buildResourceKey( - request - ) { - return new EngineKey(request).generateResourceKey() + + public static createTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string { + return EngineKey.generateTransformedDiskCacheKey(loadSrc,size,transformed,dontAnimate,redefineUrl,addOtherInfo); } + + public static createOriginalDiskCacheKey(loadSrc:string, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string { + return EngineKey.generateOriginalDiskCacheKey(loadSrc,redefineUrl,addOtherInfo); + } + + + + } diff --git a/imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets b/imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets new file mode 100644 index 0000000..8f9f051 --- /dev/null +++ b/imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 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 {RequestOption} from '../../imageknife/RequestOption' + +export interface EngineKeyInterface { + // 生成内存缓存 + generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) : string + // 生成原图变换后的图片的磁盘缓存 + generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) : string + // 生成原图的磁盘缓存 + generateOriginalDiskCacheKey(loadSrc:string) : string +} + + + diff --git a/imageknife/src/main/ets/components/imageknife/ImageKnife.ets b/imageknife/src/main/ets/components/imageknife/ImageKnife.ets index 28de40a..862666d 100644 --- a/imageknife/src/main/ets/components/imageknife/ImageKnife.ets +++ b/imageknife/src/main/ets/components/imageknife/ImageKnife.ets @@ -16,6 +16,7 @@ import { DiskLruCache } from "@ohos/disklrucache" import { LruCache } from "../cache/LruCache" import {EngineKeyFactories} from "../cache/key/EngineKeyFactories" +import {EngineKeyInterface} from "../cache/key/EngineKeyInterface" import {RequestOption} from "../imageknife/RequestOption" import {AsyncCallback} from "../imageknife/interface/asynccallback" import {PlaceHolderManager} from "../imageknife/holder/PlaceHolderManager" @@ -60,7 +61,8 @@ export class ImageKnife { private defaultLifeCycle: IDrawLifeCycle; - + // 开发者可配置全局缓存 + private engineKeyImpl: EngineKeyInterface; private constructor(imgCtx) { this.imageKnifeContext = imgCtx; @@ -85,6 +87,8 @@ export class ImageKnife { // 通用文件格式识别初始化 this.fileTypeUtil = new FileTypeUtil(); + + this.engineKeyImpl = new EngineKeyFactories(); } getMemoryCache(): LruCache{ @@ -137,6 +141,9 @@ export class ImageKnife { this.defaultLifeCycle = viewLifeCycle; } + setEngineKeyImpl(impl:EngineKeyInterface){ + this.engineKeyImpl = impl; + } private static sInstance: ImageKnife; @@ -217,18 +224,45 @@ export class ImageKnife { let cacheKey; let transferKey; let dataKey; - factories = new EngineKeyFactories(); + if(this.engineKeyImpl){ + factories = this.engineKeyImpl; + }else { + factories = new EngineKeyFactories(); + } // 生成内存缓存key 内存 变换后磁盘 - cacheKey = factories.buildCacheKey(request); + let loadKey = ''; + if(typeof request.loadSrc == 'string'){ + loadKey = request.loadSrc; + }else{ + loadKey = JSON.stringify(request.loadSrc); + } + + let size = JSON.stringify(request.size); + + let transformed = ''; + if(request && request.transformations) { + for (let i = 0; i < request.transformations.length; i++) { + if (i == request.transformations.length - 1) { + transformed += request.transformations[i].getName() + ""; + } else { + transformed += request.transformations[i].getName() + ","; + } + } + } + + let dontAnimateFlag = request.dontAnimateFlag; + + + + + cacheKey = factories.generateMemoryCacheKey(loadKey,size,transformed,dontAnimateFlag); // 生成磁盘缓存变换后数据key 变换后数据保存在磁盘 - - transferKey = factories.buildResourceKey(request); + transferKey = factories.generateTransformedDiskCacheKey(loadKey,size,transformed,dontAnimateFlag); // 生成磁盘缓存源数据key 原始数据保存在磁盘 - - dataKey = factories.buildDataKey(request); + dataKey = factories.generateOriginalDiskCacheKey(loadKey); request.generateCacheKey = cacheKey; request.generateResourceKey = transferKey; diff --git a/package.json b/package.json index a09d904..6fb348b 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,10 @@ "dependencies": { "@ohos/hypium": "1.0.3", "@ohos/hvigor-ohos-plugin": "1.4.0", + "decode-ico": "^0.4.1", "hypium": "^1.0.0", "@ohos/hvigor": "1.4.0", + "@ohos/gif-drawable": "^0.2.1", "@ohos/gpu_transform": "^0.1.0" } }