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] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E=EF=BC=9A?= =?UTF-8?q?=201=E3=80=81=E6=96=B0=E5=A2=9E=E8=87=AA=E5=AE=9A=E4=B9=89key?= =?UTF-8?q?=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