diff --git a/CHANGELOG.md b/CHANGELOG.md index 5101dde..f132572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## 2.1.2-rc.5 +- moduleContext新增缓存策略,缓存上限5,缓存策略Lru - 适配DevEco Studio 4.1(4.1.3.415)--SDK:API11( 4.1.0.56) + ## 2.1.2-rc.4 - canvas新增抗锯齿 - 修复图片缩放时出现重影 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..0903059 --- /dev/null +++ b/library/src/main/ets/components/imageknife/requestmanage/ContextCacheProxy.ets @@ -0,0 +1,80 @@ +/* + * 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 + * + * 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); + }) + } + } } }