diff --git a/CHANGELOG.md b/CHANGELOG.md index ec06963..3578558 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ - Enhance: ImageFit.Auto support adaptive height after component width change - Fix bug: call onLoadStart 2 times(import from 3.2.0-rc.0) - Change the initial value of the PixelMap component of ImageKnife to ImageContent EMPTY +- Clear memory cache, cancel pixel map release +- Loading process log modification ## 3.2.0-rc.4 - Support ICO format images diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index e585ee6..3462c30 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -48,7 +48,7 @@ export class ImageKnifeDispatcher { private engineKey: IEngineKey = new DefaultEngineKey(); showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean { - LogUtil.log('ImageKnife_DataTime_showFromMemomry.start:' + request.imageKnifeOption.loadSrc + 'requestSource=' + requestSource + ' isAnimator=' + isAnimator) + LogUtil.log('showFromMemomry.start:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion + ' isAnimator=' + isAnimator) let memoryCache: ImageKnifeData | undefined; let memoryCheckStartTime = Date.now(); if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') { @@ -81,29 +81,29 @@ export class ImageKnifeDispatcher { // 回调请求开始 if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { request.imageKnifeOption.onLoadListener.onLoadStart(request) - LogUtil.log('ImageKnife_DataTime_MemoryCache_onLoadStart:' + request.imageKnifeOption.loadSrc) + LogUtil.log('MemoryCache_onLoadStart:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion) } - LogUtil.log('ImageKnife_DataTime_MemoryCache_showPixelMap.start:' + request.imageKnifeOption.loadSrc) + this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData); + LogUtil.log('MemoryCache_showPixelMap.start:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion) request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, { width: memoryCache.imageWidth, height: memoryCache.imageHeight }, requestSource, memoryCache.imageAnimator) - LogUtil.log('ImageKnife_DataTime_MemoryCache_showPixelMap.end:' + request.imageKnifeOption.loadSrc) + LogUtil.log('MemoryCache_showPixelMap.end:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion) if (requestSource == ImageKnifeRequestSource.SRC) { request.requestState = ImageKnifeRequestState.COMPLETE // 回调请求开结束 if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) { - this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData); request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source, memoryCache, request) - LogUtil.log('ImageKnife_DataTime_MemoryCache_onLoadSuccess:' + request.imageKnifeOption.loadSrc) + LogUtil.log('MemoryCache_onLoadSuccess:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion) } } else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) { request.requestState = ImageKnifeRequestState.ERROR } } - LogUtil.log('ImageKnife_DataTime_showFromMemomry.end_hasmemory:' + request.imageKnifeOption.loadSrc) + LogUtil.log('showFromMemomry.end_hasmemory:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion) return true } - LogUtil.log('ImageKnife_DataTime_showFromMemomry.end_nomemory:' + request.imageKnifeOption.loadSrc) + LogUtil.log('showFromMemomry.end_nomemory:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion) return false } @@ -175,7 +175,7 @@ export class ImageKnifeDispatcher { } executeJob(request: ImageKnifeRequest,isAnimator?: boolean): void { - LogUtil.log('ImageKnife_DataTime_executeJob.start:' + request.imageKnifeOption.loadSrc) + LogUtil.log('executeJob.start:' + request.componentId + ',version:' + request.componentVersion) // 加载占位符 if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) { this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) @@ -183,17 +183,17 @@ export class ImageKnifeDispatcher { // 加载主图 this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator) - LogUtil.log('ImageKnife_DataTime_executeJob.end:' + request.imageKnifeOption.loadSrc) + LogUtil.log('executeJob.end:' + request.componentId + ',version:' + request.componentVersion) } /** * 获取和显示图片 */ getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void { - LogUtil.log('ImageKnife_DataTime_getAndShowImage.start:' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) if (requestSource === ImageKnifeRequestSource.SRC && currentRequest.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { currentRequest.imageKnifeOption.onLoadListener?.onLoadStart(currentRequest) - LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadStart:' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_onLoadStart:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator, currentRequest.componentWidth, currentRequest.componentHeight) @@ -206,7 +206,7 @@ export class ImageKnifeDispatcher { requestList.add({ request: currentRequest, source: requestSource }) return } - + LogUtil.info('image load getAndShowImage start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) let isWatchProgress : boolean = false if (currentRequest.imageKnifeOption.progressListener !== undefined && requestSource === ImageKnifeRequestSource.SRC) { isWatchProgress = true @@ -249,7 +249,9 @@ export class ImageKnifeDispatcher { targetWidth: currentRequest.componentWidth, targetHeight: currentRequest.componentHeight, downsampType: currentRequest.imageKnifeOption.downsampleOf == undefined ? DownsampleStrategy.DEFAULT : currentRequest.imageKnifeOption.downsampleOf, - isAutoImageFit: currentRequest.imageKnifeOption.objectFit == ImageFit.Auto + isAutoImageFit: currentRequest.imageKnifeOption.objectFit == ImageFit.Auto, + componentId: currentRequest.componentId, + componentVersion: currentRequest.componentVersion } if(request.customGetImage == undefined) { @@ -262,26 +264,26 @@ export class ImageKnifeDispatcher { if (isWatchProgress){ emitter.off(Constants.PROGRESS_EMITTER + memoryKey) } - LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.end:'+currentRequest.imageKnifeOption.loadSrc) - LogUtil.log('ImageKnife_DataTime_getAndShowImage.end:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_execute.end:'+ currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) + LogUtil.log('getAndShowImage.end:'+ currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) }) if (ImageKnife.getInstance().isRequestInSubThread){ // 启动线程下载和解码主图 - LogUtil.log('ImageKnife_DataTime_getAndShowImage_Task.start:' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('etAndShowImage_Task.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) let task = new taskpool.Task(requestJob, request) - LogUtil.log('ImageKnife_DataTime_getAndShowImage_Task.end:' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_Task.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) if (isWatchProgress){ emitter.on(Constants.PROGRESS_EMITTER + memoryKey, (data) => { this.progressCallBack(requestList! , data?.data?.value as number) }); } - LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.start(subthread):' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_execute.start(subthread):' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) taskpool.execute(task).then((res: Object) => { }).catch((err: BusinessError) => { emitter.off(Constants.CALLBACK_EMITTER + memoryKey) LogUtil.error('Fail to requestJob in sub thread src=' + imageSrc + ' err=' + err) - LogUtil.log('ImageKnife_DataTime_getAndShowImage.end:' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) if (isWatchProgress){ emitter.off(Constants.PROGRESS_EMITTER + memoryKey) } @@ -304,12 +306,12 @@ export class ImageKnifeDispatcher { }, requestList!, currentRequest, memoryKey, imageSrc, requestSource, isAnimator) }) } else { //主线程请求 - LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_execute.start(mainthread):' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) requestJob(request, requestList).then(() => { }).catch((err: BusinessError) => { emitter.off(Constants.CALLBACK_EMITTER + memoryKey) LogUtil.error('Fail to requestJob in main thread src=' + imageSrc + ' err=' + err) - LogUtil.log('ImageKnife_DataTime_getAndShowImage.end:' + currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) this.doTaskCallback({ pixelMap: undefined, @@ -347,7 +349,7 @@ export class ImageKnifeDispatcher { private doTaskCallback(requestJobResult: RequestJobResult | undefined, requestList: List , currentRequest: ImageKnifeRequest, memoryKey: string, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean):void { - LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.start:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_CallBack.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) if (requestJobResult === undefined){ return } @@ -359,7 +361,7 @@ export class ImageKnifeDispatcher { let pixelmap = requestJobResult.pixelMap; if (pixelmap === undefined) { - LogUtil.error('ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap failed:'+currentRequest.imageKnifeOption.loadSrc + " error: " + requestJobResult.loadFail) + LogUtil.error('getAndShowImage_CallBack.pixelmap failed:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion + " error: " + requestJobResult.loadFail) requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { requestWithSource.request.requestState = ImageKnifeRequestState.ERROR this.executingJobMap.remove(memoryKey); @@ -369,7 +371,7 @@ export class ImageKnifeDispatcher { requestJobResult.loadFail) { this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, requestJobResult.imageKnifeData, requestWithSource.request) requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request); - LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadFailed:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_onLoadFailed:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) { @@ -386,9 +388,9 @@ export class ImageKnifeDispatcher { } // 保存文件缓存 if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) { - LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.start:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_saveWithoutWriteFile.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize); - LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_saveWithoutWriteFile.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } let imageKnifeData: ImageKnifeData; @@ -426,11 +428,11 @@ export class ImageKnifeDispatcher { // 保存内存缓存 if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) { - LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_saveMemoryCache.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) ImageKnife.getInstance() .saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator, currentRequest.componentWidth, currentRequest.componentHeight), saveCacheImageData); - LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_saveMemoryCache.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } if (requestList !== undefined) { // key相同的request,一起绘制 @@ -441,11 +443,12 @@ export class ImageKnifeDispatcher { requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER || (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER && requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) { - LogUtil.log('ImageKnife_DataTime_getAndShowImage_showPixelMap.start:'+currentRequest.imageKnifeOption.loadSrc) + this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, imageKnifeData,requestWithSource.request); + LogUtil.log('getAndShowImage_showPixelMap.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight }, requestWithSource.source, imageKnifeData.imageAnimator); - LogUtil.log('ImageKnife_DataTime_getAndShowImage_showPixelMap.end:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_showPixelMap.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } if (requestWithSource.source == ImageKnifeRequestSource.SRC) { @@ -453,10 +456,9 @@ export class ImageKnifeDispatcher { if (requestWithSource.request.imageKnifeOption.onLoadListener && requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) { // 回调请求成功 - this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, imageKnifeData,requestWithSource.request); requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source, saveCacheImageData, requestWithSource.request); - LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadSuccess:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_onLoadSuccess:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } } else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) { requestWithSource.request.requestState = ImageKnifeRequestState.ERROR; @@ -476,6 +478,7 @@ export class ImageKnifeDispatcher { } } this.assembleImageKnifeData(callBackData,requestJobResult.imageKnifeData,requestWithSource.request) + LogUtil.log('getAndShowImage cancel:' + requestWithSource.request.componentId + ',srcType:' + requestSource + ',version:' + requestWithSource.request.componentVersion) requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', requestWithSource.request) } } @@ -486,12 +489,12 @@ export class ImageKnifeDispatcher { } else { LogUtil.log('error: no requestlist need to draw for key = ' + memoryKey); } - LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.end:'+currentRequest.imageKnifeOption.loadSrc) + LogUtil.log('getAndShowImage_CallBack.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) } dispatchNextJob() { - LogUtil.log('ImageKnife_DataTime_dispatchNextJob.start') + LogUtil.log('dispatchNextJob.start') // 主图和错误图并发加载时,以及主图加载失败后立即加载错误图,可能会导致短时间内并发数超过maxRequests,故此处减少响应的并发 if (this.executingJobMap.length >= this.maxRequests) { @@ -501,13 +504,13 @@ export class ImageKnifeDispatcher { while (true) { let request = this.jobQueue.pop() if (request === undefined) { - LogUtil.log('ImageKnife_DataTime_dispatchNextJob.end:no any job') + LogUtil.log('dispatchNextJob.end:no any job') break // 队列已无任务 } else if (request.requestState === ImageKnifeRequestState.PROGRESS) { - LogUtil.log('ImageKnife_DataTime_dispatchNextJob.start executeJob:' + request.imageKnifeOption.loadSrc) + LogUtil.log('dispatchNextJob.start executeJob:' + request.componentId + ',version:' + request.componentVersion) this.executeJob(request) - LogUtil.log('ImageKnife_DataTime_dispatchNextJob.end executeJob:' + request.imageKnifeOption.loadSrc) + LogUtil.log('dispatchNextJob.end executeJob:' + request.componentId + ',version:' + request.componentVersion) break }else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) { //构建回调错误信息 @@ -522,6 +525,7 @@ export class ImageKnifeDispatcher { }; callBackData.errorInfo = errorInfo; } + LogUtil.log('dispatchNextJob cancel:' + request.componentId + ',version:' + request.componentVersion) request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', request) } } @@ -550,7 +554,7 @@ export class ImageKnifeDispatcher { */ @Concurrent async function requestJob(request: RequestJobRequest, requestList?: List) { - LogUtil.log('ImageKnife_DataTime_requestJob.start:' + request.src + ' requestSource=' + request.requestSource) + LogUtil.log('requestJob.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) let src = typeof request.src == 'number' ? request.resName != undefined ? request.resName : request.src + '' : request.src // 生成文件缓存key let fileKey = request.engineKey.generateFileKey(src, request.signature, request.isAnimator) diff --git a/library/src/main/ets/ImageKnifeLoader.ets b/library/src/main/ets/ImageKnifeLoader.ets index 2a71b22..3db23e6 100644 --- a/library/src/main/ets/ImageKnifeLoader.ets +++ b/library/src/main/ets/ImageKnifeLoader.ets @@ -35,6 +35,7 @@ import util from '@ohos.util'; import { FileTypeUtil } from './utils/FileTypeUtil'; import { DownsampleStrategy } from './downsampling/DownsampleStartegy'; import { Downsampler } from './downsampling/Downsampler'; +import { common } from '@kit.AbilityKit'; class RequestData { receiveSize: number = 2000 @@ -53,8 +54,14 @@ export class ImageKnifeLoader { callBackData.bufSize = resBuf.byteLength; let typeValue = new FileTypeUtil().getFileType(resBuf); if(typeValue == null) { - LogUtil.log('ImageKnife_DataTime_requestJob.end: getFileType is null ' + request.src) - ImageKnifeLoader.makeEmptyResult(request,'request is not a valid image source', ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT, LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE)) + let unit8 = new Uint8Array(resBuf) + LogUtil.log('requestJob.end: getFileType is null: ' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) + ImageKnifeLoader.makeEmptyResult(request, + 'request is not a valid image source:' + request.componentId + ',srcType:' + request.requestSource + ',' + + request.componentVersion + ',buffer:' + resBuf.byteLength + ',unit8:' + unit8[0] + ',' + + unit8[1] + ',' + unit8[2], + ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT, + LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE)) return } callBackData.type = typeValue; @@ -163,9 +170,9 @@ export class ImageKnifeLoader { return }) if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) { - LogUtil.log('ImageKnife_DataTime_requestJob.transform.start:' + request.src) + LogUtil.log('requestJob.transform.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) resPixelmap = await request.transformation?.transform(request.context, resPixelmap, request.componentWidth, request.componentHeight); - LogUtil.log('ImageKnife_DataTime_requestJob.transform.end:' + request.src) + LogUtil.log('requestJob.transform.end:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) } try { resPixelmap?.setTransferDetached(true) @@ -402,9 +409,9 @@ export class ImageKnifeLoader { static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string, callBackData: ImageKnifeData){ // 保存文件缓存 if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) { - LogUtil.log('ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:'+request.src) + LogUtil.log('requestJob_saveFileCacheOnlyFile.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder) - LogUtil.log('ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:'+request.src) + LogUtil.log('requestJob_saveFileCacheOnlyFile.end:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) } ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData) } @@ -433,7 +440,7 @@ export class ImageKnifeLoader { resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) callBackTimeInfo.diskCheckEndTime = Date.now(); if (resBuf === undefined) { - LogUtil.log('start customGetImage src=' + request.src) + LogUtil.log('start customGetImage src=' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) const headerObj: Record = ImageKnifeLoader.getHeaderObj(request) try { request.customGetImage(request.context, request.src, headerObj) @@ -451,7 +458,7 @@ export class ImageKnifeLoader { loadError = 'customGetImage loadFail failed' ImageKnifeLoader.makeEmptyResult(request,loadError + e, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE)) } - LogUtil.log('end customGetImage src=' + request.src) + LogUtil.log('end customGetImage src=' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) return } } @@ -464,10 +471,10 @@ export class ImageKnifeLoader { resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) callBackTimeInfo.diskCheckEndTime = Date.now() if (resBuf !== undefined){ - LogUtil.log('success get image from filecache for key = ' + fileKey + ' src = ' + request.src) + LogUtil.log('success get image from filecache for key = ' + fileKey + ' src = ' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) } else if (request.onlyRetrieveFromCache != true) { - LogUtil.log('HttpDownloadClient.start:' + request.src) + LogUtil.log('HttpDownloadClient.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) callBackTimeInfo.netRequestStartTime = Date.now(); let httpRequest = http.createHttp(); let progress: number = 0 @@ -525,7 +532,7 @@ export class ImageKnifeLoader { callBackTimeInfo.netRequestEndTime = Date.now(); ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE, undefined)) }); - LogUtil.log('HttpDownloadClient.end:' + request.src) + LogUtil.log('HttpDownloadClient.end:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion) return } else { @@ -552,7 +559,7 @@ export class ImageKnifeLoader { ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE) loadError = 'LoadDataShareFileClient fs.open err happened uri=' + request.src + ' err.msg=' + err?.message + ' err.code=' + err?.code }) - } else { //从本地文件获取 + } else if (ImageKnifeLoader.isLocalLoadSrc(request.context, request.src)) { //从本地文件获取 ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE) try { let stat = fs.statSync(request.src); @@ -564,8 +571,10 @@ export class ImageKnifeLoader { } } catch (err) { ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE, LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE) - loadError = err + loadError = 'LocalLoadSrc:' + request.src + ',err:' + err } + } else { + loadError = 'Parameter not supported:' + request.src } } else if (typeof request.src == 'number') { //从资源文件获取 let manager = request.context.createModuleContext(request.moduleName).resourceManager @@ -594,7 +603,16 @@ export class ImageKnifeLoader { } ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData) } - + static isLocalLoadSrc(context: Object | undefined, loadSrc: string): boolean { + if (context != undefined) { + let fileDir: string = (context as common.UIAbilityContext).filesDir as string; + let cacheDir: string = (context as common.UIAbilityContext).cacheDir as string + if (loadSrc.startsWith(fileDir) || loadSrc.startsWith(cacheDir)) { + return true; + } + } + return false; + } static getDownsamplerDecodingOptions(typeValue: string, request: RequestJobRequest, size: Size, SRC?: ImageKnifeRequestSource):image.DecodingOptions { let reqSize = diff --git a/library/src/main/ets/cache/FileCache.ets b/library/src/main/ets/cache/FileCache.ets index afffb48..414241d 100644 --- a/library/src/main/ets/cache/FileCache.ets +++ b/library/src/main/ets/cache/FileCache.ets @@ -60,6 +60,7 @@ export class FileCache { if (this.isInited) { return } + let startTime = Date.now() if (this.context && path.startsWith(this.context.cacheDir) === true) { this.path = path } else { @@ -104,6 +105,7 @@ export class FileCache { } this.trimToSize(); + LogUtil.info('image init initFileCache:' + (Date.now() - startTime) + ',num:' + filenames.length + ',nums:' + this.lruCache.length + ',size:' + this.currentMemory) this.isInited = true } diff --git a/library/src/main/ets/cache/MemoryLruCache.ets b/library/src/main/ets/cache/MemoryLruCache.ets index 282907f..a9060f7 100644 --- a/library/src/main/ets/cache/MemoryLruCache.ets +++ b/library/src/main/ets/cache/MemoryLruCache.ets @@ -115,7 +115,7 @@ export class MemoryLruCache implements IMemoryCache { } } else { this.currentMemory -= value.source.getPixelBytesNumber(); - value.source.release() + // value.source.release() } // LogUtil.info('MemoryCache removeMemorySize: ' + value.source.getPixelBytesNumber() + ' currentMemory:' + this.currentMemory) } diff --git a/library/src/main/ets/components/ImageKnifeComponent.ets b/library/src/main/ets/components/ImageKnifeComponent.ets index 7953a88..a977487 100644 --- a/library/src/main/ets/components/ImageKnifeComponent.ets +++ b/library/src/main/ets/components/ImageKnifeComponent.ets @@ -110,7 +110,8 @@ export struct ImageKnifeComponent { if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize) { this.isImageFitAutoResize = false } else { - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) + ImageKnife.getInstance().execute(this.getRequest( + this.currentWidth, this.currentHeight, this.getUniqueId())) } } } @@ -127,7 +128,8 @@ export struct ImageKnifeComponent { ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc + ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc + ' componentId = ' + this.getUniqueId()) - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) + ImageKnife.getInstance().execute(this.getRequest( + this.currentWidth, this.currentHeight, this.getUniqueId())) } getCurrentContext(): common.UIAbilityContext { @@ -137,7 +139,7 @@ export struct ImageKnifeComponent { return this.currentContext } - getRequest(width: number, height: number): ImageKnifeRequest { + getRequest(width: number, height: number,componentId: number): ImageKnifeRequest { this.request = new ImageKnifeRequest( this.imageKnifeOption, this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(), @@ -150,8 +152,15 @@ export struct ImageKnifeComponent { return //针对reuse场景,不显示历史图片 } this.pixelMap = pixelMap - LogUtil.debug('image load showPixelMap:' + this.request?.imageKnifeOption.loadSrc + ', componentId = ' + - this.getUniqueId() + ',size:' + JSON.stringify(size)) + let memory = this.request?.imageKnifeData?.timeInfo?.memoryCheckEndTime ? 1 : 0 + let fileCache = this.request?.imageKnifeData?.timeInfo?.diskCheckEndTime ? 1 : 0 + let net = this.request?.imageKnifeData?.timeInfo?.netRequestEndTime ? 1 : 0 + memory = memory - fileCache + fileCache = fileCache - net + let source = memory == 1 ? 'memory' : fileCache == 1 ? 'fileCache' : 'downLoad' + LogUtil.info('image load showPixelMap:' + this.request?.componentId + ',srcType:' + requestSource + + ',version:' + this.request?.componentVersion + + ',size:' + JSON.stringify(size) + ',source:' + source) if (typeof this.pixelMap !== 'string') { if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize == false) { this.adaptiveHeight = this.currentWidth * size.height / size.width @@ -170,7 +179,9 @@ export struct ImageKnifeComponent { this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit } } - }) + }, + componentId + ) return this.request } } diff --git a/library/src/main/ets/model/ImageKnifeData.ets b/library/src/main/ets/model/ImageKnifeData.ets index 5bcde11..bddfbe4 100644 --- a/library/src/main/ets/model/ImageKnifeData.ets +++ b/library/src/main/ets/model/ImageKnifeData.ets @@ -151,6 +151,8 @@ export interface RequestJobRequest { targetWidth: number targetHeight: number downsampType: DownsampleStrategy, - isAutoImageFit: boolean + isAutoImageFit: boolean, + componentId?: number, + componentVersion?: number } diff --git a/library/src/main/ets/model/ImageKnifeRequest.ets b/library/src/main/ets/model/ImageKnifeRequest.ets index ca5749c..ff00e2d 100644 --- a/library/src/main/ets/model/ImageKnifeRequest.ets +++ b/library/src/main/ets/model/ImageKnifeRequest.ets @@ -28,18 +28,20 @@ export class ImageKnifeRequest { componentVersion: number = 0 headers: Map = new Map() imageKnifeData?: ImageKnifeData + componentId?: number constructor(option: ImageKnifeOption, uIAbilityContext: common.UIAbilityContext, width: number, height: number, version: number, - ImageKnifeRequestCallback: ImageKnifeRequestCallback) { + ImageKnifeRequestCallback: ImageKnifeRequestCallback,componentId?: number) { this.imageKnifeOption = option this.context = uIAbilityContext this.componentWidth = width this.componentHeight = height this.componentVersion = version this.ImageKnifeRequestCallback = ImageKnifeRequestCallback + this.componentId = componentId } // RequestOption调用header对于的方法 addHeader(key: string, value: Object) {