From e65ee6bb811ebcdfbeb4efee132fb6b5e1300730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E6=9C=88=E6=B8=85=E9=A3=8E?= Date: Mon, 29 Apr 2024 15:06:14 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=EF=BC=9A=201=E3=80=81=E6=96=B0=E5=A2=9E=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89key=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 明月清风 --- CHANGELOG.md | 15 ++-- .../main/ets/common/CustomEngineKeyImpl.ets | 46 ++++++++++++ .../main/ets/entryability/EntryAbility.ets | 6 +- entry/src/main/ets/pages/Index.ets | 5 ++ .../src/main/ets/pages/SignatureTestPage.ets | 72 +++++++++++++++++++ .../resources/base/profile/main_pages.json | 3 +- library/index.ets | 4 ++ library/src/main/ets/ImageKnife.ets | 6 ++ library/src/main/ets/ImageKnifeDispatcher.ets | 57 ++++++--------- library/src/main/ets/ImageKnifeOption.ets | 4 ++ library/src/main/ets/ImageKnifeRequest.ets | 1 - .../ets/components/ImageKnifeComponent.ets | 38 +++++----- .../src/main/ets/key/EngineKeyFactories.ets | 48 +++++++++++++ .../src/main/ets/key/EngineKeyInterface.ets | 23 ++++++ library/src/main/ets/model/ObjectKey.ets | 28 ++++++++ library/src/main/ets/utils/FileCache.ets | 17 +++-- 16 files changed, 300 insertions(+), 73 deletions(-) create mode 100644 entry/src/main/ets/common/CustomEngineKeyImpl.ets create mode 100644 entry/src/main/ets/pages/SignatureTestPage.ets create mode 100644 library/src/main/ets/key/EngineKeyFactories.ets create mode 100644 library/src/main/ets/key/EngineKeyInterface.ets create mode 100644 library/src/main/ets/model/ObjectKey.ets diff --git a/CHANGELOG.md b/CHANGELOG.md index 218ba8b..d87db28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.0.0-rc.0 -使用Image组件替换Canvas组件渲染,并重构大部分的实现逻辑,提升渲染性能 - +- 使用Image组件替换Canvas组件渲染,并重构大部分的实现逻辑,提升渲染性能 +- 补齐自定key特性 + 较2.x版本增强点: - 使用Image组件代替Canvas组件渲染 - 重构Dispatch分发逻辑,支持控制并发请求数,支持请求排队队列的优先级 @@ -9,7 +10,7 @@ - 继承Image的能力,支持option传入border,设置边框,圆角 - 继承Image的能力,支持option传入objectFit设置图片缩放 - 修复发送消息时最近的两条消息头像闪动的问题 - + 缺失特性 - 不支持drawLifeCycle接口,通过canvas自会图片 - mainScaleType,border等参数,新版本与系统Image保持一致 @@ -249,12 +250,12 @@ 新增 - - 1.onClick事件属性 + - 1.onClick事件属性 - 删除 + 删除 - - 1.size(设置大小) - - 2.sizeAnimated 显式动画 + - 1.size(设置大小) + - 2.sizeAnimated 显式动画 - 3.backgroundColor背景色 - 4.margin 组件外间距 等属性,删除的属性将由通用属性提供支持,可支持在ImageKnifeComponent自定义组件上链式调用 ## 1.0.4 diff --git a/entry/src/main/ets/common/CustomEngineKeyImpl.ets b/entry/src/main/ets/common/CustomEngineKeyImpl.ets new file mode 100644 index 0000000..887e678 --- /dev/null +++ b/entry/src/main/ets/common/CustomEngineKeyImpl.ets @@ -0,0 +1,46 @@ +/* + * 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 { EngineKeyInterface, ObjectKey } from '@ohos/imageknife'; +import util from '@ohos.util'; +import { SparkMD5 } from '@ohos/imageknife/src/main/ets/3rd_party/sparkmd5/spark-md5'; + +//全局自定义key demo +export class CustomEngineKeyImpl implements EngineKeyInterface { + private keyCache: util.LRUCache = new util.LRUCache(1024) + + // 生成内存缓存 + generateCacheKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string { + let key = "loadSrc=" + this.generateKey(loadSrc) + ";"; + if (signature) { + key += "signature=" + signature.getKey() + ";" + } + return key; + } + + // key缓存策略,避免无意义的 JSON.stringify + private generateKey(key: string | PixelMap | Resource): string { + let keyCache = typeof key == "string" ? key : JSON.stringify(key) + let result = this.keyCache.get(keyCache) + if (result != undefined) { + return result + } else { + result = SparkMD5.hashBinary(keyCache) + this.keyCache.put(keyCache, result) + return result + } + } + + +} diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index 675efde..91250a1 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -17,7 +17,8 @@ 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,LogUtil } from '@ohos/imageknife'; +import { ImageKnife, LogUtil } from '@ohos/imageknife'; +import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { @@ -32,9 +33,10 @@ export default class EntryAbility extends UIAbility { // Main window is created, set main page for this ability hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + LogUtil.mLogLevel = LogUtil.ALL // 初始化ImageKnife的文件缓存 await ImageKnife.getInstance().initFileCache(this.context, 256, 256 * 1024 * 1024) - LogUtil.mLogLevel = LogUtil.ALL + ImageKnife.getInstance().setEngineKeyImpl(new CustomEngineKeyImpl()) windowStage.loadContent('pages/Index', (err, data) => { if (err.code) { hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 71da2ac..41abf54 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -62,7 +62,12 @@ struct Index { }); }) + Button("自定义key").margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/SignatureTestPage', + }); + }) } .width('100%') diff --git a/entry/src/main/ets/pages/SignatureTestPage.ets b/entry/src/main/ets/pages/SignatureTestPage.ets new file mode 100644 index 0000000..2e862d5 --- /dev/null +++ b/entry/src/main/ets/pages/SignatureTestPage.ets @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021 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, ImageKnifeOption, ObjectKey } from '@ohos/imageknife'; + + +@Entry +@Component +struct SignatureTestPage { + @State imageKnifeOption1: ImageKnifeOption = + { + loadSrc: $r('app.media.icon'), + placeholderSrc:$r("app.media.loading"), + }; + @State imageKnifeOption2: ImageKnifeOption = + { + loadSrc: $r('app.media.icon'), + placeholderSrc:$r("app.media.loading"), + }; + + build() { + Scroll() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + + Text("Signature固定为 1").fontSize(15) + Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Button("加载") + .onClick(() => { + this.imageKnifeOption1 = { + loadSrc: 'https://img-blog.csdn.net/20140514114029140', + placeholderSrc:$r("app.media.loading"), + signature: new ObjectKey("1") + } + }).margin({ top: 5, left: 3 }) + ImageKnifeComponent({ ImageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) + }.width('100%').backgroundColor(Color.Pink) + + Text("设置Signature,每次为时间戳").fontSize(15) + Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Button("加载") + .onClick(() => { + this.imageKnifeOption2 = { + loadSrc: 'https://img-blog.csdn.net/20140514114029140', + placeholderSrc:$r("app.media.loading"), + signature: new ObjectKey(new Date().getTime().toString()) + } + }).margin({ top: 5, left: 3 }) + ImageKnifeComponent({ ImageKnifeOption: this.imageKnifeOption2 }).width(300).height(300) + }.width('100%').backgroundColor(Color.Pink) + } + + }.width('100%') + .height('100%') + + } + + aboutToAppear() { + console.log("唯一标识页面:" + new ObjectKey(new Date().getTime().toString()).getKey()) + + } +} \ 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 5b02dd4..10c4911 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -7,6 +7,7 @@ "pages/LongImagePage", "pages/TransformPage", "pages/UserPage", - "pages/TestImageFlash" + "pages/TestImageFlash", + "pages/SignatureTestPage" ] } \ No newline at end of file diff --git a/library/index.ets b/library/index.ets index b6c20fd..afc1896 100644 --- a/library/index.ets +++ b/library/index.ets @@ -10,3 +10,7 @@ export { FileUtils } from './src/main/ets/utils/FileUtils' export { LogUtil } from './src/main/ets/utils/LogUtil' +export { EngineKeyInterface } from './src/main/ets/key/EngineKeyInterface' + +export { ObjectKey } from './src/main/ets/model/ObjectKey' + diff --git a/library/src/main/ets/ImageKnife.ets b/library/src/main/ets/ImageKnife.ets index c529d4b..2c4498b 100644 --- a/library/src/main/ets/ImageKnife.ets +++ b/library/src/main/ets/ImageKnife.ets @@ -18,6 +18,7 @@ import { MemoryLruCache } from './utils/MemoryLruCache'; import { IMemoryCache } from './utils/IMemoryCache' import { FileCache } from './utils/FileCache'; import { ImageKnifeDispatcher } from './ImageKnifeDispatcher'; +import { EngineKeyInterface } from './key/EngineKeyInterface'; export class ImageKnife { @@ -120,4 +121,9 @@ export class ImageKnife { setMaxRequests(concurrency: number): void { this.dispatcher.setMaxRequests(concurrency) } + + setEngineKeyImpl(impl: EngineKeyInterface): void { + this.dispatcher.setEngineKeyImpl(impl); + } + } \ No newline at end of file diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index a2428fb..163c056 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -31,8 +31,9 @@ import { Constants } from './utils/Constants'; import taskpool from '@ohos.taskpool'; import { FileTypeUtil } from './utils/FileTypeUtil'; import util from '@ohos.util'; -import { Tools } from './utils/Tools'; import { SparkMD5 } from './3rd_party/sparkmd5/spark-md5'; +import { EngineKeyInterface } from './key/EngineKeyInterface'; +import { EngineKeyFactories } from './key/EngineKeyFactories'; export class ImageKnifeDispatcher { // 最大并发 @@ -41,12 +42,12 @@ export class ImageKnifeDispatcher { private jobQueue: IJobQueue = new DefaultJobQueue() // 执行中的请求 executingJobMap: LightWeightMap> = new LightWeightMap(); + // 开发者可配置全局缓存 + private engineKeyImpl: EngineKeyInterface = new EngineKeyFactories(); - private keyCache: util.LRUCache = new util.LRUCache(1024) - - showFromMemomry(request: ImageKnifeRequest,imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean { + showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean { let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance() - .loadFromMemoryCache(Tools.generateMemoryKey(imageSrc)) + .loadFromMemoryCache(this.engineKeyImpl.generateCacheKey(imageSrc, request.ImageKnifeOption.signature)) if (memoryCache !== undefined) { // 画主图 if (request.requestState === ImageKnifeRequestState.PROGRESS) { @@ -63,22 +64,11 @@ export class ImageKnifeDispatcher { return false } - // 生成唯一的key - generateKey(key: string | PixelMap | Resource): string { - let keyCache = typeof key == "string"? key : JSON.stringify(key) - let result = this.keyCache.get(keyCache) - if(result != undefined) { - return result - } else { - result = SparkMD5.hashBinary(keyCache) - this.keyCache.put(keyCache,result) - return result - } - } + enqueue(request: ImageKnifeRequest): void { //1.内存有的话直接渲染 - if (this.showFromMemomry(request,request.ImageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC)) { + if (this.showFromMemomry(request, request.ImageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC)) { return } @@ -93,7 +83,7 @@ export class ImageKnifeDispatcher { executeJob(request: ImageKnifeRequest): void { // 加载占位符 if (request.ImageKnifeOption.placeholderSrc !== undefined) { - if (this.showFromMemomry(request,request.ImageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) === false) { + if (this.showFromMemomry(request, request.ImageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) === false) { this.getAndShowImage(request, request.ImageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) } } @@ -106,7 +96,7 @@ export class ImageKnifeDispatcher { * 获取和显示图片 */ getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): void { - let key: string = Tools.generateKey(imageSrc) + let key: string = this.engineKeyImpl.generateCacheKey(imageSrc, currentRequest.ImageKnifeOption.signature) let requestList: List | undefined = this.executingJobMap.get(key) if (requestList == undefined) { requestList = new List() @@ -141,7 +131,7 @@ export class ImageKnifeDispatcher { requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { if (requestWithSource.source === ImageKnifeRequestSource.SRC && currentRequest.ImageKnifeOption.errorholderSrc !== undefined) { - if (this.showFromMemomry(currentRequest,currentRequest.ImageKnifeOption.errorholderSrc, ImageKnifeRequestSource.ERROR_HOLDER) === false) { + if (this.showFromMemomry(currentRequest, currentRequest.ImageKnifeOption.errorholderSrc, ImageKnifeRequestSource.ERROR_HOLDER) === false) { this.getAndShowImage(currentRequest, currentRequest.ImageKnifeOption.errorholderSrc, ImageKnifeRequestSource.ERROR_HOLDER) } } @@ -164,21 +154,22 @@ export class ImageKnifeDispatcher { } // 保存内存缓存 - ImageKnife.getInstance().saveMemoryCache(Tools.generateMemoryKey(imageSrc), ImageKnifeData) + ImageKnife.getInstance() + .saveMemoryCache(this.engineKeyImpl.generateCacheKey(imageSrc, currentRequest.ImageKnifeOption.signature), ImageKnifeData) if (requestList !== undefined) { // todo 判断request生命周期,已销毁的不需要再绘制 // key相同的request,一起绘制 requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { - if (requestWithSource.request.requestState === ImageKnifeRequestState.DESTROY){ + if (requestWithSource.request.requestState === ImageKnifeRequestState.DESTROY) { return } // 画主图 if (requestWithSource.source === ImageKnifeRequestSource.SRC || requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER || (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER && requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) { - requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion , ImageKnifeData.source) + requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, ImageKnifeData.source) } if (requestWithSource.source == ImageKnifeRequestSource.SRC) { @@ -201,15 +192,9 @@ export class ImageKnifeDispatcher { } dispatchNextJob() { - while (true) { - let request = this.jobQueue.pop() - if (request === undefined){ - break// 队列已无任务 - } - else if (request.requestState === ImageKnifeRequestState.PROGRESS) { - this.executeJob(request) - break - } + let request = this.jobQueue.pop() + if (request !== undefined) { + this.executeJob(request) } } @@ -218,6 +203,10 @@ export class ImageKnifeDispatcher { this.maxRequests = concurrency } } + + setEngineKeyImpl(impl: EngineKeyInterface): void { + this.engineKeyImpl = impl; + } } /** @@ -329,7 +318,7 @@ async function requestJob(request: RequestJobRequest): Promise Promise diff --git a/library/src/main/ets/ImageKnifeRequest.ets b/library/src/main/ets/ImageKnifeRequest.ets index 892bf43..943786f 100644 --- a/library/src/main/ets/ImageKnifeRequest.ets +++ b/library/src/main/ets/ImageKnifeRequest.ets @@ -19,7 +19,6 @@ import common from '@ohos.app.ability.common'; import { SparkMD5 } from './3rd_party/sparkmd5/spark-md5' import { LogUtil } from './utils/LogUtil' import { ImageKnifeRequestSource } from './ImageKnifeDispatcher'; -import { Tools } from './utils/Tools'; export class ImageKnifeRequest { diff --git a/library/src/main/ets/components/ImageKnifeComponent.ets b/library/src/main/ets/components/ImageKnifeComponent.ets index 66cafbb..3b26200 100644 --- a/library/src/main/ets/components/ImageKnifeComponent.ets +++ b/library/src/main/ets/components/ImageKnifeComponent.ets @@ -20,7 +20,6 @@ import { LogUtil } from '../utils/LogUtil'; import componentUtils from '@ohos.arkui.componentUtils' import util from '@ohos.util' import inspector from '@ohos.arkui.inspector' -import { Tools } from '../utils/Tools'; import { ImageKnifeData } from '../model/ImageKnifeData' @Component @@ -34,7 +33,6 @@ export struct ImageKnifeComponent { private lastHeight: number = 0 private currentWidth: number = 0 private currentHeight: number = 0 - private lastSrc: string | PixelMap | Resource = ""; private componentVersion: number = 0 private currentContext: common.UIAbilityContext | undefined = undefined @State keyCanvas: KeyCanvas = { @@ -43,16 +41,17 @@ export struct ImageKnifeComponent { private listener: inspector.ComponentObserver = inspector.createComponentObserver(this.keyCanvas.keyId) aboutToAppear(): void { - let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance() - .loadFromMemoryCache(Tools.generateMemoryKey(this.ImageKnifeOption.loadSrc)) - if (memoryCache !== undefined){ - LogUtil.log("aboutToAppear load from memory cache for key = "+ Tools.generateMemoryKey(this.ImageKnifeOption.loadSrc)) - //画主图 - this.pixelMap = memoryCache.source; - }else { - LogUtil.log("aboutToAppear onLayoutComplete") - this.listener.on("layout", this.onLayoutComplete) - } + //闪动问题失效,注释相应代码后续修复 + // let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance() + // .loadFromMemoryCache(Tools.generateMemoryKey(this.ImageKnifeOption.loadSrc)) + // if (memoryCache !== undefined){ + // LogUtil.log("aboutToAppear load from memory cache for key = "+ Tools.generateMemoryKey(this.ImageKnifeOption.loadSrc)) + // //画主图 + // this.pixelMap = memoryCache.source; + // }else { + LogUtil.log("aboutToAppear onLayoutComplete") + this.listener.on("layout", this.onLayoutComplete) + // } } @@ -79,14 +78,12 @@ export struct ImageKnifeComponent { } watchImageKnifeOption() { - if (this.lastSrc !== this.ImageKnifeOption.loadSrc) { - if (this.request !== undefined) { - this.request.requestState = ImageKnifeRequestState.DESTROY - } - this.request = undefined - this.componentVersion++ - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) - } + if (this.request !== undefined) { + this.request.requestState = ImageKnifeRequestState.DESTROY + } + this.request = undefined + this.componentVersion++ + ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) } getCurrentContext(): common.UIAbilityContext{ if(this.currentContext == undefined) { @@ -96,7 +93,6 @@ export struct ImageKnifeComponent { } getRequest(width: number, height: number): ImageKnifeRequest { if (this.request == undefined) { - this.lastSrc = this.ImageKnifeOption.loadSrc this.request = new ImageKnifeRequest( this.ImageKnifeOption, this.ImageKnifeOption.context !== undefined ? this.ImageKnifeOption.context : this.getCurrentContext(), diff --git a/library/src/main/ets/key/EngineKeyFactories.ets b/library/src/main/ets/key/EngineKeyFactories.ets new file mode 100644 index 0000000..078f574 --- /dev/null +++ b/library/src/main/ets/key/EngineKeyFactories.ets @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 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 util from '@ohos.util'; +import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'; +import { ObjectKey } from '../model/ObjectKey'; +import { EngineKeyInterface } from './EngineKeyInterface'; + +export class EngineKeyFactories implements EngineKeyInterface { + + private keyCache: util.LRUCache = new util.LRUCache(1024) + + // 生成内存缓存 + generateCacheKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string { + let key = "loadSrc=" + this.generateKey(loadSrc) + ";"; + if (signature) { + key += "signature=" + signature.getKey() + ";" + } + return key; + } + + // key缓存策略,避免无意义的 JSON.stringify + private generateKey(key: string | PixelMap | Resource): string { + let keyCache = typeof key == "string" ? key : JSON.stringify(key) + let result = this.keyCache.get(keyCache) + if (result != undefined) { + return result + } else { + result = SparkMD5.hashBinary(keyCache) + this.keyCache.put(keyCache, result) + return result + } + } +} + + + diff --git a/library/src/main/ets/key/EngineKeyInterface.ets b/library/src/main/ets/key/EngineKeyInterface.ets new file mode 100644 index 0000000..1e127ed --- /dev/null +++ b/library/src/main/ets/key/EngineKeyInterface.ets @@ -0,0 +1,23 @@ +/* + * 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 { ObjectKey } from '../model/ObjectKey' + +export interface EngineKeyInterface { + // 生成缓存key + generateCacheKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string +} + + + diff --git a/library/src/main/ets/model/ObjectKey.ets b/library/src/main/ets/model/ObjectKey.ets new file mode 100644 index 0000000..9a121ae --- /dev/null +++ b/library/src/main/ets/model/ObjectKey.ets @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 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 ObjectKey{ + + private objectKey: string; + + constructor(objectKey: string) { + this.objectKey = objectKey; + } + + getKey(): string{ + return this.objectKey; + } + + +} \ No newline at end of file diff --git a/library/src/main/ets/utils/FileCache.ets b/library/src/main/ets/utils/FileCache.ets index b55b334..4260966 100644 --- a/library/src/main/ets/utils/FileCache.ets +++ b/library/src/main/ets/utils/FileCache.ets @@ -16,6 +16,7 @@ import util from '@ohos.util'; import { FileUtils } from './FileUtils'; import fs from '@ohos.file.fs'; import { LogUtil } from './LogUtil'; +import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'; /** @@ -172,8 +173,8 @@ export class FileCache { let remove: number | undefined = this.lruCache.remove(key) if (remove !== undefined) { - FileUtils.getInstance().deleteFile(this.path + key) - this.removeMemorySize(remove) + FileUtils.getInstance().deleteFile(this.path + key) + this.removeMemorySize(remove) } } @@ -204,10 +205,10 @@ export class FileCache { break } let delkey = this.lruCache.keys()[0] - let remove: number | undefined = this.lruCache.remove(this.lruCache.keys()[0]) - if (remove !== undefined) { + let data: ArrayBuffer | undefined = FileUtils.getInstance().readFileSync(this.path + delkey) + if (data !== undefined) { FileUtils.getInstance().deleteFile(this.path + delkey) - this.removeMemorySize(remove) + this.removeMemorySize(data) } this.lruCache.remove(delkey) } @@ -242,8 +243,9 @@ export class FileCache { */ static saveFileCacheOnlyFile(context: Context, key: string, value: ArrayBuffer): boolean { // 写文件 + let md5Key = SparkMD5.hashBinary(key) FileUtils.getInstance() - .writeFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + key, value) + .writeFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + md5Key, value) return true } @@ -255,7 +257,8 @@ export class FileCache { */ static getFileCacheByFile(context: Context, key: string): ArrayBuffer | undefined { // 从文件获取查看是否有缓存 + let md5Key = SparkMD5.hashBinary(key) return FileUtils.getInstance() - .readFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + key) + .readFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + md5Key) } } \ No newline at end of file From 34cb7e64ea222343f58f893e9138b2bb5f7446f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E6=9C=88=E6=B8=85=E9=A3=8E?= Date: Tue, 30 Apr 2024 10:06:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=EF=BC=9A=201=E3=80=81=E8=A7=84=E8=8C=83=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 明月清风 --- entry/src/main/ets/common/CustomEngineKeyImpl.ets | 4 ++-- library/index.ets | 5 ++++- library/src/main/ets/ImageKnife.ets | 4 ++-- library/src/main/ets/ImageKnifeDispatcher.ets | 9 ++++----- .../key/{EngineKeyFactories.ets => DefaultEngineKey.ets} | 4 ++-- .../ets/key/{EngineKeyInterface.ets => IEngineKey.ets} | 2 +- library/src/main/ets/utils/FileCache.ets | 6 ++---- 7 files changed, 17 insertions(+), 17 deletions(-) rename library/src/main/ets/key/{EngineKeyFactories.ets => DefaultEngineKey.ets} (92%) rename library/src/main/ets/key/{EngineKeyInterface.ets => IEngineKey.ets} (95%) diff --git a/entry/src/main/ets/common/CustomEngineKeyImpl.ets b/entry/src/main/ets/common/CustomEngineKeyImpl.ets index 887e678..6bbb9a1 100644 --- a/entry/src/main/ets/common/CustomEngineKeyImpl.ets +++ b/entry/src/main/ets/common/CustomEngineKeyImpl.ets @@ -12,12 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { EngineKeyInterface, ObjectKey } from '@ohos/imageknife'; import util from '@ohos.util'; +import { IEngineKey, ObjectKey } from '@ohos/imageknife'; import { SparkMD5 } from '@ohos/imageknife/src/main/ets/3rd_party/sparkmd5/spark-md5'; //全局自定义key demo -export class CustomEngineKeyImpl implements EngineKeyInterface { +export class CustomEngineKeyImpl implements IEngineKey { private keyCache: util.LRUCache = new util.LRUCache(1024) // 生成内存缓存 diff --git a/library/index.ets b/library/index.ets index afc1896..255f3d7 100644 --- a/library/index.ets +++ b/library/index.ets @@ -10,7 +10,10 @@ export { FileUtils } from './src/main/ets/utils/FileUtils' export { LogUtil } from './src/main/ets/utils/LogUtil' -export { EngineKeyInterface } from './src/main/ets/key/EngineKeyInterface' +export { IEngineKey } from './src/main/ets/key/IEngineKey' export { ObjectKey } from './src/main/ets/model/ObjectKey' + + + diff --git a/library/src/main/ets/ImageKnife.ets b/library/src/main/ets/ImageKnife.ets index 2c4498b..3d35f83 100644 --- a/library/src/main/ets/ImageKnife.ets +++ b/library/src/main/ets/ImageKnife.ets @@ -18,7 +18,7 @@ import { MemoryLruCache } from './utils/MemoryLruCache'; import { IMemoryCache } from './utils/IMemoryCache' import { FileCache } from './utils/FileCache'; import { ImageKnifeDispatcher } from './ImageKnifeDispatcher'; -import { EngineKeyInterface } from './key/EngineKeyInterface'; +import { IEngineKey } from './key/IEngineKey'; export class ImageKnife { @@ -122,7 +122,7 @@ export class ImageKnife { this.dispatcher.setMaxRequests(concurrency) } - setEngineKeyImpl(impl: EngineKeyInterface): void { + setEngineKeyImpl(impl: IEngineKey): void { this.dispatcher.setEngineKeyImpl(impl); } diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index 163c056..1287ad6 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -31,9 +31,8 @@ import { Constants } from './utils/Constants'; import taskpool from '@ohos.taskpool'; import { FileTypeUtil } from './utils/FileTypeUtil'; import util from '@ohos.util'; -import { SparkMD5 } from './3rd_party/sparkmd5/spark-md5'; -import { EngineKeyInterface } from './key/EngineKeyInterface'; -import { EngineKeyFactories } from './key/EngineKeyFactories'; +import { IEngineKey } from './key/IEngineKey'; +import { DefaultEngineKey } from './key/DefaultEngineKey'; export class ImageKnifeDispatcher { // 最大并发 @@ -43,7 +42,7 @@ export class ImageKnifeDispatcher { // 执行中的请求 executingJobMap: LightWeightMap> = new LightWeightMap(); // 开发者可配置全局缓存 - private engineKeyImpl: EngineKeyInterface = new EngineKeyFactories(); + private engineKeyImpl: IEngineKey = new DefaultEngineKey(); showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean { let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance() @@ -204,7 +203,7 @@ export class ImageKnifeDispatcher { } } - setEngineKeyImpl(impl: EngineKeyInterface): void { + setEngineKeyImpl(impl: IEngineKey): void { this.engineKeyImpl = impl; } } diff --git a/library/src/main/ets/key/EngineKeyFactories.ets b/library/src/main/ets/key/DefaultEngineKey.ets similarity index 92% rename from library/src/main/ets/key/EngineKeyFactories.ets rename to library/src/main/ets/key/DefaultEngineKey.ets index 078f574..6c66985 100644 --- a/library/src/main/ets/key/EngineKeyFactories.ets +++ b/library/src/main/ets/key/DefaultEngineKey.ets @@ -15,9 +15,9 @@ import util from '@ohos.util'; import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'; import { ObjectKey } from '../model/ObjectKey'; -import { EngineKeyInterface } from './EngineKeyInterface'; +import { IEngineKey } from './IEngineKey'; -export class EngineKeyFactories implements EngineKeyInterface { +export class DefaultEngineKey implements IEngineKey { private keyCache: util.LRUCache = new util.LRUCache(1024) diff --git a/library/src/main/ets/key/EngineKeyInterface.ets b/library/src/main/ets/key/IEngineKey.ets similarity index 95% rename from library/src/main/ets/key/EngineKeyInterface.ets rename to library/src/main/ets/key/IEngineKey.ets index 1e127ed..d832d79 100644 --- a/library/src/main/ets/key/EngineKeyInterface.ets +++ b/library/src/main/ets/key/IEngineKey.ets @@ -14,7 +14,7 @@ */ import { ObjectKey } from '../model/ObjectKey' -export interface EngineKeyInterface { +export interface IEngineKey { // 生成缓存key generateCacheKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string } diff --git a/library/src/main/ets/utils/FileCache.ets b/library/src/main/ets/utils/FileCache.ets index 4260966..eaf357e 100644 --- a/library/src/main/ets/utils/FileCache.ets +++ b/library/src/main/ets/utils/FileCache.ets @@ -243,9 +243,8 @@ export class FileCache { */ static saveFileCacheOnlyFile(context: Context, key: string, value: ArrayBuffer): boolean { // 写文件 - let md5Key = SparkMD5.hashBinary(key) FileUtils.getInstance() - .writeFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + md5Key, value) + .writeFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + key, value) return true } @@ -257,8 +256,7 @@ export class FileCache { */ static getFileCacheByFile(context: Context, key: string): ArrayBuffer | undefined { // 从文件获取查看是否有缓存 - let md5Key = SparkMD5.hashBinary(key) return FileUtils.getInstance() - .readFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + md5Key) + .readFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + key) } } \ No newline at end of file