1.新增功能:支持自定义缓存key

2.添加缓存key中的url需要剔除token的演示界面

Signed-off-by: zhoulisheng1 <zhoulisheng1@huawei.com>
This commit is contained in:
zhoulisheng1 2023-03-16 17:39:59 +08:00
parent c6c269fb3e
commit 1b5aea1138
11 changed files with 234 additions and 87 deletions

View File

@ -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;
}
}

View File

@ -1,7 +1,8 @@
import UIAbility from '@ohos.app.ability.UIAbility'; import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog'; import hilog from '@ohos.hilog';
import window from '@ohos.window'; 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 { export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) { onCreate(want, launchParam) {
@ -9,6 +10,8 @@ export default class EntryAbility extends UIAbility {
globalThis.ImageKnife = ImageKnife.with(this.context); globalThis.ImageKnife = ImageKnife.with(this.context);
// 全局配置网络加载进度条 // 全局配置网络加载进度条
globalThis.ImageKnife.setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5)) globalThis.ImageKnife.setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5))
// 全局配置缓存key
globalThis.ImageKnife.setEngineKeyImpl(new CustomEngineKeyImpl())
} }
onDestroy() { onDestroy() {

View File

@ -12,16 +12,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import {ImageKnifeComponent} from '@ohos/imageknife' import {
import {ImageKnifeOption} from '@ohos/imageknife' ImageKnifeComponent,
import {RotateImageTransformation} from '@ohos/imageknife' ImageKnifeOption,
import {RoundedCornersTransformation} from '@ohos/imageknife' RotateImageTransformation,
RoundedCornersTransformation
} from '@ohos/imageknife'
@Entry @Entry
@Component @Component
struct FrescoImageTestCasePage { struct CacheRuleChangedPage {
@State progresshint: string = "输出加载百分比回调信息"
@State progresshint:string = "输出加载百分比回调信息"
@State imageKnifeOption1: ImageKnifeOption = @State imageKnifeOption1: ImageKnifeOption =
{ {
loadSrc: "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83ericA1Mv66TwicuYOtbDMBcUhv1aa9RJBeAn9uURfcZD0AUGrJebAn1g2AjN0vb2E1XTET7fTuLBNmA/132", loadSrc: "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83ericA1Mv66TwicuYOtbDMBcUhv1aa9RJBeAn9uURfcZD0AUGrJebAn1g2AjN0vb2E1XTET7fTuLBNmA/132",
@ -50,6 +51,14 @@ struct FrescoImageTestCasePage {
{ {
loadSrc: "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", 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'), placeholderSrc: $r('app.media.icon_loading'),
errorholderSrc: $r('app.media.icon_failed'), errorholderSrc: $r('app.media.icon_failed'),
displayProgress: true, displayProgress: true,
@ -58,17 +67,35 @@ struct FrescoImageTestCasePage {
build() { build() {
Scroll() { Scroll() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 })
// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }) Text('下图默认加载网络图片不带?token=').margin({top:20})
// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption3 }) 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 }) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption4 })
.width(300) .width(300)
.height(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%') .width('100%')

View File

@ -127,12 +127,12 @@ struct IndexFunctionDemo {
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
}.width('100%').height(60).backgroundColor(Color.Pink) }.width('100%').height(60).backgroundColor(Color.Pink)
Text("测试fresco").fontSize(15) Text("测试缓存规则和重试").fontSize(15)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button("加载百分比") Button("更改缓存规则")
.onClick(() => { .onClick(() => {
console.log("加载百分比") console.log("更改缓存规则")
router.push({ uri: "pages/frescoImageTestCasePage" }); router.push({ uri: "pages/CacheRuleChangedPage" });
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
Button("重试Retry") Button("重试Retry")
.onClick(() => { .onClick(() => {

View File

@ -1,7 +1,7 @@
{ {
"src": [ "src": [
"pages/index", "pages/index",
"pages/frescoImageTestCasePage", "pages/CacheRuleChangedPage",
"pages/frescoRetryTestCasePage", "pages/frescoRetryTestCasePage",
"pages/basicTestFeatureAbilityPage", "pages/basicTestFeatureAbilityPage",
"pages/basicTestFileIOPage", "pages/basicTestFileIOPage",

View File

@ -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/DATA'
export * from './src/main/ets/components/cache/diskstrategy/enum/NONE' 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/diskstrategy/enum/RESOURCE'
export * from './src/main/ets/components/cache/key/EngineKeyInterface'
export * from './src/main/ets/components/cache/key/EngineKeyFactories'
/** /**
* compress * compress

View File

@ -17,76 +17,50 @@ import {RequestOption} from '../../imageknife/RequestOption'
import {BaseTransform} from '../../imageknife/transform/BaseTransform' import {BaseTransform} from '../../imageknife/transform/BaseTransform'
export class EngineKey implements Key { export class EngineKey implements Key {
private request: RequestOption;
constructor(
request
) {
this.request = request;
}
// 内存缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目 // 内存缓存 缓存生成规则:是否会影响图片内容,不影响则通用(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); if(redefine){
loadSrc = redefine(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() + ",";
} }
}
}
let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag);
let key = "loadSrc=" + loadSrc + ";" + let key = "loadSrc=" + loadSrc + ";" +
"size=" + size + ";" + "size=" + size + ";" +
"transformations=" + transformationsStr + ";" + "transformations=" + transformed + ";" +
"dontAnimateFlag=" + dontAnimateFlag + ";" "dontAnimateFlag=" + dontAnimate + ";"
if(otherInfo){
key += otherInfo;
}
return key; return key;
} }
// 磁盘缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目 // 磁盘缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目
// 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图) // 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图)
generateResourceKey(): string{ public static generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{
if(redefine){
let loadSrc = JSON.stringify(this.request.loadSrc); loadSrc = redefine(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() + ",";
} }
}
}
let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag);
let key = "loadSrc=" + loadSrc + ";" + let key = "loadSrc=" + loadSrc + ";" +
"size=" + size + ";" + "size=" + size + ";" +
"transformations=" + transformationsStr + ";" + "transformations=" + transformed + ";" +
"dontAnimateFlag=" + dontAnimateFlag + ";" "dontAnimateFlag=" + dontAnimate + ";"
if(otherInfo){
key += otherInfo;
}
return key; return key;
} }
// 磁盘缓存 // 磁盘缓存
// 生成网络加载数据 原始数据存于磁盘的key // 生成网络加载数据 原始数据存于磁盘的key
generateDataKey(): string{ public static generateOriginalDiskCacheKey(loadSrc:string, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{
let loadSrc = JSON.stringify(this.request.loadSrc); if(redefine){
loadSrc = redefine(loadSrc);
}
let key = "loadSrc=" + loadSrc + ";" let key = "loadSrc=" + loadSrc + ";"
if(otherInfo){
key += otherInfo;
}
return key; return key;
} }

View File

@ -13,24 +13,39 @@
* limitations under the License. * limitations under the License.
*/ */
import {EngineKey} from '../key/EngineKey' import {EngineKey} from '../key/EngineKey'
import {EngineKeyInterface} from '../key/EngineKeyInterface'
import {RequestOption} from '../../imageknife/RequestOption'
export class EngineKeyFactories { export class EngineKeyFactories implements EngineKeyInterface {
buildCacheKey( // 生成内存缓存
request) { generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) {
return new EngineKey(request).generateCacheKey(); 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( public static createMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string{
request return EngineKey.generateMemoryCacheKey(loadSrc,size,transformed,dontAnimate,redefineUrl,addOtherInfo);
) {
return new EngineKey(request).generateDataKey()
} }
buildResourceKey(
request 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);
return new EngineKey(request).generateResourceKey()
} }
public static createOriginalDiskCacheKey(loadSrc:string, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string {
return EngineKey.generateOriginalDiskCacheKey(loadSrc,redefineUrl,addOtherInfo);
}
} }

View File

@ -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
}

View File

@ -16,6 +16,7 @@
import { DiskLruCache } from "@ohos/disklrucache" import { DiskLruCache } from "@ohos/disklrucache"
import { LruCache } from "../cache/LruCache" import { LruCache } from "../cache/LruCache"
import {EngineKeyFactories} from "../cache/key/EngineKeyFactories" import {EngineKeyFactories} from "../cache/key/EngineKeyFactories"
import {EngineKeyInterface} from "../cache/key/EngineKeyInterface"
import {RequestOption} from "../imageknife/RequestOption" import {RequestOption} from "../imageknife/RequestOption"
import {AsyncCallback} from "../imageknife/interface/asynccallback" import {AsyncCallback} from "../imageknife/interface/asynccallback"
import {PlaceHolderManager} from "../imageknife/holder/PlaceHolderManager" import {PlaceHolderManager} from "../imageknife/holder/PlaceHolderManager"
@ -60,7 +61,8 @@ export class ImageKnife {
private defaultLifeCycle: IDrawLifeCycle; private defaultLifeCycle: IDrawLifeCycle;
// 开发者可配置全局缓存
private engineKeyImpl: EngineKeyInterface;
private constructor(imgCtx) { private constructor(imgCtx) {
this.imageKnifeContext = imgCtx; this.imageKnifeContext = imgCtx;
@ -85,6 +87,8 @@ export class ImageKnife {
// 通用文件格式识别初始化 // 通用文件格式识别初始化
this.fileTypeUtil = new FileTypeUtil(); this.fileTypeUtil = new FileTypeUtil();
this.engineKeyImpl = new EngineKeyFactories();
} }
getMemoryCache(): LruCache<string, any>{ getMemoryCache(): LruCache<string, any>{
@ -137,6 +141,9 @@ export class ImageKnife {
this.defaultLifeCycle = viewLifeCycle; this.defaultLifeCycle = viewLifeCycle;
} }
setEngineKeyImpl(impl:EngineKeyInterface){
this.engineKeyImpl = impl;
}
private static sInstance: ImageKnife; private static sInstance: ImageKnife;
@ -217,18 +224,45 @@ export class ImageKnife {
let cacheKey; let cacheKey;
let transferKey; let transferKey;
let dataKey; let dataKey;
if(this.engineKeyImpl){
factories = this.engineKeyImpl;
}else {
factories = new EngineKeyFactories(); factories = new EngineKeyFactories();
}
// 生成内存缓存key 内存 变换后磁盘 // 生成内存缓存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 变换后数据保存在磁盘 // 生成磁盘缓存变换后数据key 变换后数据保存在磁盘
transferKey = factories.generateTransformedDiskCacheKey(loadKey,size,transformed,dontAnimateFlag);
transferKey = factories.buildResourceKey(request);
// 生成磁盘缓存源数据key 原始数据保存在磁盘 // 生成磁盘缓存源数据key 原始数据保存在磁盘
dataKey = factories.generateOriginalDiskCacheKey(loadKey);
dataKey = factories.buildDataKey(request);
request.generateCacheKey = cacheKey; request.generateCacheKey = cacheKey;
request.generateResourceKey = transferKey; request.generateResourceKey = transferKey;

View File

@ -13,8 +13,10 @@
"dependencies": { "dependencies": {
"@ohos/hypium": "1.0.3", "@ohos/hypium": "1.0.3",
"@ohos/hvigor-ohos-plugin": "1.4.0", "@ohos/hvigor-ohos-plugin": "1.4.0",
"decode-ico": "^0.4.1",
"hypium": "^1.0.0", "hypium": "^1.0.0",
"@ohos/hvigor": "1.4.0", "@ohos/hvigor": "1.4.0",
"@ohos/gif-drawable": "^0.2.1",
"@ohos/gpu_transform": "^0.1.0" "@ohos/gpu_transform": "^0.1.0"
} }
} }