From ea87330bb3d9dcfec03d99ce9b483c922b75bbcb 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, 15 Jan 2024 16:38:32 +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=81moduleContext=E6=96=B0=E5=A2=9E=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E7=AD=96=E7=95=A5=EF=BC=8C=E7=BC=93=E5=AD=98=E4=B8=8A?= =?UTF-8?q?=E9=99=905=EF=BC=8C=E7=BC=93=E5=AD=98=E7=AD=96=E7=95=A5Lru?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 明月清风 --- CHANGELOG.md | 3 + library/oh-package.json5 | 2 +- .../main/ets/components/cache/LruCache.ets | 26 +++--- .../compress/provider/RecourseProvider.ets | 39 +++++---- .../requestmanage/ContextCacheProxy.ets | 80 +++++++++++++++++++ .../resourcemanage/ParseResClient.ets | 31 ++++--- .../resourcemanage/ParseResClientBase64.ets | 7 +- .../transform/MaskTransformation.ets | 48 ++++++----- 8 files changed, 172 insertions(+), 64 deletions(-) create mode 100644 library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets diff --git a/CHANGELOG.md b/CHANGELOG.md index ca09887..03c4cbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2.1.2-rc.5 +- moduleContext新增缓存策略,缓存上限5,缓存策略Lru + ## 2.1.2-rc.4 - canvas新增抗锯齿 - 修复图片缩放时出现重影 diff --git a/library/oh-package.json5 b/library/oh-package.json5 index b1437f0..ad41c10 100644 --- a/library/oh-package.json5 +++ b/library/oh-package.json5 @@ -14,7 +14,7 @@ "main": "index.ets", "repository": "https://gitee.com/openharmony-tpc/ImageKnife", "type": "module", - "version": "2.1.2-rc.4", + "version": "2.1.2-rc.5", "dependencies": { "pako": "^2.1.0", "@ohos/disklrucache": "^2.0.2-rc.0", diff --git a/library/src/main/ets/components/cache/LruCache.ets b/library/src/main/ets/components/cache/LruCache.ets index f873924..ef27540 100644 --- a/library/src/main/ets/components/cache/LruCache.ets +++ b/library/src/main/ets/components/cache/LruCache.ets @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {CustomMap} from './CustomMap' +import { CustomMap } from './CustomMap' -export class LruCache { +export class LruCache { maxsize: number = 0 size: number = 0; map: CustomMap = new CustomMap(); @@ -39,7 +39,7 @@ export class LruCache { } // 移除键为key的缓存 - remove(key: K): V | undefined{ + remove(key: K): V | undefined { if (key == null) { throw new Error('key is null,checking the parameter'); } @@ -51,7 +51,7 @@ export class LruCache { } // 获取键为key的value - get(key: K): V|undefined { + get(key: K): V | undefined { if (key == null) { throw new Error('key is null,checking the parameter'); } @@ -62,6 +62,11 @@ export class LruCache { return preValue } + // 是否存在key + has(key: K): boolean { + return this.map.hasKey(key); + } + /* * 替换或删除对应key键的数据 * evicted:是否删除 @@ -96,12 +101,12 @@ export class LruCache { } // 缓存数据数量 - sizeLength(): number{ + sizeLength(): number { return this.size } // 缓存数据最大值 - maxSize(): number{ + maxSize(): number { return this.maxsize } @@ -119,21 +124,20 @@ export class LruCache { this.trimToSize(-1) } - print():string { + print(): string { let printResult = ''; if (this.map.isEmpty()) { return printResult; } - this.map.each( (value, key, index) => { - printResult +='LruCache:key=' + key + 'value= ' + value; + this.map.each((value, key, index) => { + printResult += 'LruCache:key=' + key + 'value= ' + value; }) return printResult; } - foreachLruCache(fn:(value: V, key: K, map: Map) => void){ + foreachLruCache(fn: (value: V, key: K, map: Map) => void) { this.map.each(fn); } - } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/compress/provider/RecourseProvider.ets b/library/src/main/ets/components/imageknife/compress/provider/RecourseProvider.ets index 4bc0b0c..aac034f 100644 --- a/library/src/main/ets/components/imageknife/compress/provider/RecourseProvider.ets +++ b/library/src/main/ets/components/imageknife/compress/provider/RecourseProvider.ets @@ -20,6 +20,7 @@ import { ImageKnifeGlobal } from '../../ImageKnifeGlobal'; import resourceManager from '@ohos.resourceManager'; import { BusinessError } from '@ohos.base' import common from '@ohos.app.ability.common'; +import { ContextCacheProxy } from '../../requestmanage/ContextCacheProxy'; export class RecourseProvider extends CompressAdapter { private static CHARS: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; @@ -46,30 +47,34 @@ export class RecourseProvider extends CompressAdapter { if (!this._mResourceData) { throw Error("compress resource is empty"); } - ((ImageKnifeGlobal.getInstance() - .getHapContext() as common.UIAbilityContext).createModuleContext(this._mResourceData.moduleName).resourceManager as resourceManager.ResourceManager) - .getMediaContent(this._mResourceData.id) - .then(data => { - let buffer = this.uint8ArrayToBuffer(data); - let fileTypeUtil = new FileTypeUtil() - let fileType = fileTypeUtil.getFileType(buffer); - if(fileType != null) { - this._mPixelMapHeader = fileType; - } - callback.compressDataListener(buffer); - }) - .catch((err: BusinessError) => { - console.log("RecourseProvider openInternal err" + JSON.stringify(err as BusinessError)); - }) - + let context = ContextCacheProxy.getInstance() + .contextGetValue(this._mResourceData.moduleName, + ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext); + if (context != undefined) { + (context.resourceManager as resourceManager.ResourceManager) + .getMediaContent(this._mResourceData.id) + .then(data => { + let buffer = this.uint8ArrayToBuffer(data); + let fileTypeUtil = new FileTypeUtil() + let fileType = fileTypeUtil.getFileType(buffer); + if (fileType != null) { + this._mPixelMapHeader = fileType; + } + callback.compressDataListener(buffer); + }) + .catch((err: BusinessError) => { + console.log("RecourseProvider openInternal err" + JSON.stringify(err as BusinessError)); + }) + } } - getPixelMapFormat(): PixelMapFormat|undefined{ + getPixelMapFormat(): PixelMapFormat | undefined { if (!this._mPixelMapHeader) { return PixelMapFormat.NONE; } return this.getFormat(this._mPixelMapHeader); } + /** * data decode */ diff --git a/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets b/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets new file mode 100644 index 0000000..984f0d9 --- /dev/null +++ b/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets @@ -0,0 +1,80 @@ +/* + * 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 { ICache } from "../requestmanage/ICache" +import { LruCache } from "../../cache/LruCache" + +export class ContextCacheProxy implements ICache { + private mLruCache: LruCache; + private static cache: ContextCacheProxy = new ContextCacheProxy(new LruCache(5)); + + private constructor(lruCache: LruCache) { + this.mLruCache = lruCache; + } + + public static getInstance(): ContextCacheProxy { + return ContextCacheProxy.cache; + } + + + // 缓存类型 + getName() { + return "ContextCacheProxy" + } + + contextGetValue(key: string, context: Context): Context | undefined{ + if (this.hasValue(key)) { + return this.getValue(key); + } else { + let moduleContext = context.createModuleContext(key); + this.putValue(key, moduleContext) + return moduleContext; + } + } + + getValue(key: string): Context | undefined { + return this.mLruCache.get(key); + } + + hasValue(key: string): boolean { + return this.mLruCache.has(key); + } + + putValue(key: string, value: Context) { + this.mLruCache.put(key, value); + } + + removeValue(key: string): Context | undefined { + return this.mLruCache.remove(key); + } + + clear() { + this.mLruCache.evicAll(); + } + + + // 外界调用 + loadMemoryCache(key: string, isMemoryCacheable: boolean): Context | null { + // 是否开启内存缓存 + if (!isMemoryCacheable) { + return null; + } + let cached = this.getValue(key) + if (cached != null) { + return cached; + } + return null; + } +} \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/resourcemanage/ParseResClient.ets b/library/src/main/ets/components/imageknife/resourcemanage/ParseResClient.ets index 297f101..7839571 100644 --- a/library/src/main/ets/components/imageknife/resourcemanage/ParseResClient.ets +++ b/library/src/main/ets/components/imageknife/resourcemanage/ParseResClient.ets @@ -13,26 +13,33 @@ * limitations under the License. */ -import {IResourceFetch} from '../resourcemanage/IResourceFetch' -import {ResourceTypeEts} from '../../imageknife/constants/ResourceTypeEts' +import { IResourceFetch } from '../resourcemanage/IResourceFetch' +import { ResourceTypeEts } from '../../imageknife/constants/ResourceTypeEts' import resourceManager from '@ohos.resourceManager'; import { ImageKnifeGlobal } from '../ImageKnifeGlobal'; import { BusinessError } from '@ohos.base' import common from '@ohos.app.ability.common'; +import { ContextCacheProxy } from '../requestmanage/ContextCacheProxy'; + export class ParseResClient implements IResourceFetch { - loadResource(context:common.UIAbilityContext,res: Resource, onCompleteFunction:(value:ArrayBuffer)=>void | PromiseLike, onErrorFunction:(reason?:BusinessError|string)=>void) { + loadResource(context: common.UIAbilityContext, res: Resource, onCompleteFunction: (value: ArrayBuffer) => void | PromiseLike, onErrorFunction: (reason?: BusinessError | string) => void) { let resId = res.id; let resType = res.type; if (resType == ResourceTypeEts.MEDIA) { - (context.createModuleContext(res.moduleName).resourceManager as resourceManager.ResourceManager) - .getMediaContent(resId) - .then(data => { - let arrayBuffer = this.typedArrayToBuffer(data); - onCompleteFunction(arrayBuffer) - }) - .catch( (err:BusinessError) => { - onErrorFunction(err) - }) + let moduleContext = ContextCacheProxy.getInstance() + .contextGetValue(res.moduleName, context); + if (moduleContext != undefined) { + (moduleContext.resourceManager as resourceManager.ResourceManager) + .getMediaContent(resId) + .then(data => { + let arrayBuffer = this.typedArrayToBuffer(data); + onCompleteFunction(arrayBuffer) + }) + .catch((err: BusinessError) => { + onErrorFunction(err) + }) + } + } else if (resType == ResourceTypeEts.RAWFILE) { onErrorFunction('ParseResClient 本地资源是rawfile暂时无法解析出错') diff --git a/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets b/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets index 857efe2..2f8510f 100644 --- a/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets +++ b/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets @@ -20,13 +20,16 @@ import { BusinessError } from '@ohos.base' import resourceManager from '@ohos.resourceManager'; import { ImageKnifeGlobal } from '../ImageKnifeGlobal'; import common from '@ohos.app.ability.common' +import { ContextCacheProxy } from '../requestmanage/ContextCacheProxy' export class ParseResClientBase64 implements IResourceFetch { - loadResource(context:common.UIAbilityContext,res: Resource, onCompleteFunction: (value: ArrayBuffer) => void | PromiseLike, onErrorFunction: (reason?: BusinessError | string) => void) { + loadResource(context: common.UIAbilityContext, res: Resource, onCompleteFunction: (value: ArrayBuffer) => void | PromiseLike, onErrorFunction: (reason?: BusinessError | string) => void) { let resId = res.id; let resType = res.type; if (resType == ResourceTypeEts.MEDIA) { - (context.createModuleContext(res.moduleName).resourceManager as resourceManager.ResourceManager) + let moduleContext = ContextCacheProxy.getInstance() + .contextGetValue(res.moduleName, context); + (moduleContext.resourceManager as resourceManager.ResourceManager) .getMediaContentBase64(resId) .then(data => { let matchReg = ';base64,'; diff --git a/library/src/main/ets/components/imageknife/transform/MaskTransformation.ets b/library/src/main/ets/components/imageknife/transform/MaskTransformation.ets index ceddd0a..ed7d7d0 100644 --- a/library/src/main/ets/components/imageknife/transform/MaskTransformation.ets +++ b/library/src/main/ets/components/imageknife/transform/MaskTransformation.ets @@ -26,6 +26,7 @@ import resourceManager from '@ohos.resourceManager' import { BusinessError } from '@ohos.base' import {Size} from '../../imageknife/RequestOption' import common from '@ohos.app.ability.common' +import { ContextCacheProxy } from '../requestmanage/ContextCacheProxy' export class MaskTransformation implements BaseTransform { private _mResourceData:Resource|undefined = undefined; @@ -96,27 +97,32 @@ export class MaskTransformation implements BaseTransform { let context = (request.getModuleContext() as common.UIAbilityContext) if(context != undefined){ if(this._mResourceData != undefined){ - let resourceManager = context.createModuleContext(this._mResourceData.moduleName).resourceManager as resourceManager.ResourceManager - if(resourceManager != undefined && this._mResourceData != undefined) - resourceManager.getMediaContent(this._mResourceData?.id) - .then(array => { - let buffer = array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset); - let imageSource:image.ImageSource = image.createImageSource(buffer); - let options:image.DecodingOptions = { - editable: true, - desiredSize: { - width: width, - height: height - } - } - imageSource.createPixelMap(options) - .then(maskBitmap => { - MaskUtils.mask(bitmap, maskBitmap, func) - }) - }) - .catch((err:BusinessError) => { - func?.asyncTransform("MaskTransformation openInternal error" + err, null); - }) + let moduleContext = ContextCacheProxy.getInstance() + .contextGetValue(this._mResourceData.moduleName, context); + if (moduleContext != undefined) { + let resourceManager = moduleContext.resourceManager as resourceManager.ResourceManager + if(resourceManager != undefined && this._mResourceData != undefined) + resourceManager.getMediaContent(this._mResourceData?.id) + .then(array => { + let buffer = array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset); + let imageSource:image.ImageSource = image.createImageSource(buffer); + let options:image.DecodingOptions = { + editable: true, + desiredSize: { + width: width, + height: height + } + } + imageSource.createPixelMap(options) + .then(maskBitmap => { + MaskUtils.mask(bitmap, maskBitmap, func) + }) + }) + .catch((err:BusinessError) => { + func?.asyncTransform("MaskTransformation openInternal error" + err, null); + }) + } + } } } From cd245a606180d1554943455e25f72e1bd5a6f442 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, 16 Jan 2024 06:37:55 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=89=88=E6=9D=83?= =?UTF-8?q?=E5=A4=B4=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 明月清风 --- .../components/imageknife/requestmanage/ContextCacheProxy.ets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets b/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets index 984f0d9..0903059 100644 --- a/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets +++ b/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at