新增接口回调信息功能

Signed-off-by: tyBrave <tianyong21@h-partners.com>
This commit is contained in:
tyBrave 2024-10-25 22:48:53 +08:00
parent 1a2326c691
commit b57194cf4c
7 changed files with 415 additions and 64 deletions

View File

@ -346,7 +346,7 @@ export class ImageKnife {
* @param cacheType * @param cacheType
* @returns * @returns
*/ */
getCacheUpperLimit(cacheType?: CacheStrategy): number | undefined { getCacheLimitSize(cacheType?: CacheStrategy): number | undefined {
if (cacheType == undefined || cacheType == CacheStrategy.Default) { if (cacheType == undefined || cacheType == CacheStrategy.Default) {
cacheType = CacheStrategy.Memory; cacheType = CacheStrategy.Memory;
} }
@ -366,7 +366,7 @@ export class ImageKnife {
* @param cacheType * @param cacheType
* @returns * @returns
*/ */
getCurrentPicturesNum(cacheType: CacheStrategy): number | undefined { getCurrentCacheNum(cacheType: CacheStrategy): number | undefined {
if (cacheType == undefined || cacheType == CacheStrategy.Default) { if (cacheType == undefined || cacheType == CacheStrategy.Default) {
cacheType = CacheStrategy.Memory; cacheType = CacheStrategy.Memory;
} }

View File

@ -19,10 +19,10 @@ import List from '@ohos.util.List';
import LightWeightMap from '@ohos.util.LightWeightMap'; import LightWeightMap from '@ohos.util.LightWeightMap';
import { LogUtil } from './utils/LogUtil'; import { LogUtil } from './utils/LogUtil';
import { ImageKnife } from './ImageKnife'; import { ImageKnife } from './ImageKnife';
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData'; import { ImageKnifeData, CacheStrategy, TimeInfo, ErrorInfo } from './model/ImageKnifeData';
import image from '@ohos.multimedia.image'; import image from '@ohos.multimedia.image';
import emitter from '@ohos.events.emitter'; import emitter from '@ohos.events.emitter';
import { Constants } from './utils/Constants'; import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants';
import taskpool from '@ohos.taskpool'; import taskpool from '@ohos.taskpool';
import { FileTypeUtil } from './utils/FileTypeUtil'; import { FileTypeUtil } from './utils/FileTypeUtil';
import { IEngineKey } from './key/IEngineKey'; import { IEngineKey } from './key/IEngineKey';
@ -50,6 +50,7 @@ export class ImageKnifeDispatcher {
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean { 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("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc + "requestSource=" + requestSource + " isAnimator=" + isAnimator)
let memoryCache: ImageKnifeData | undefined; let memoryCache: ImageKnifeData | undefined;
let memoryCheckStartTime = Date.now();
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') { if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
memoryCache = { memoryCache = {
source: request.imageKnifeOption.loadSrc as image.PixelMap, source: request.imageKnifeOption.loadSrc as image.PixelMap,
@ -61,12 +62,25 @@ export class ImageKnifeDispatcher {
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator)); .loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
} }
//记录ImageKnifeRequestSource.SRC 开始内存检查的时间点
if (requestSource == ImageKnifeRequestSource.SRC && request.getImageKnifeData()) {
let timeInfo = request.getImageKnifeData()?.timeInfo
if (timeInfo) {
timeInfo.memoryCheckStartTime = memoryCheckStartTime;
timeInfo.memoryCheckEndTime = Date.now();
//设置请求结束的时间点
if (memoryCache !== undefined) {
timeInfo.requestEndTime = Date.now();
}
}
}
if (memoryCache !== undefined) { if (memoryCache !== undefined) {
// 画主图 // 画主图
if (request.requestState === ImageKnifeRequestState.PROGRESS) { if (request.requestState === ImageKnifeRequestState.PROGRESS) {
// 回调请求开始 // 回调请求开始
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
request.imageKnifeOption.onLoadListener.onLoadStart() request.imageKnifeOption.onLoadListener.onLoadStart(request)
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
} }
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
@ -77,7 +91,8 @@ export class ImageKnifeDispatcher {
request.requestState = ImageKnifeRequestState.COMPLETE request.requestState = ImageKnifeRequestState.COMPLETE
// 回调请求开结束 // 回调请求开结束
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) { if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source,memoryCache) this.copyMemoryCacheInfo(memoryCache, request.getImageKnifeData());
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source, memoryCache, request)
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
} }
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) { } else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
@ -91,8 +106,55 @@ export class ImageKnifeDispatcher {
return false return false
} }
private copyMemoryCacheInfo(memoryCache: ImageKnifeData | undefined, target: ImageKnifeData | undefined) {
if (!memoryCache || !target) {
return;
}
target.source = memoryCache.source;
target.imageWidth = memoryCache.imageWidth;
target.imageHeight = memoryCache.imageHeight;
target.type = memoryCache.type;
target.imageAnimator = memoryCache.imageAnimator;
}
private assembleImageKnifeData(beforeCallData: ImageKnifeData | undefined, afterCallData: ImageKnifeData | undefined, req: ImageKnifeRequest) {
if (!beforeCallData || !afterCallData || !req) {
return;
}
//设置图片开始加载时间及其缓存检查时间点
if (beforeCallData.timeInfo) {
if (afterCallData.timeInfo) {
afterCallData.timeInfo.requestStartTime = beforeCallData.timeInfo.requestStartTime;
afterCallData.timeInfo.memoryCheckStartTime = beforeCallData.timeInfo.memoryCheckStartTime;
afterCallData.timeInfo.memoryCheckEndTime = beforeCallData.timeInfo.memoryCheckEndTime;
}
}
req.setImageKnifeData(afterCallData);
}
private initCallData(request: ImageKnifeRequest) {
if (!request) {
return
}
//图片加载信息回调数据
let callBackData: ImageKnifeData = {
source: "",
imageWidth: 0,
imageHeight: 0,
};
//图片加载信息回调数据时间点
let callBackTimeInfo: TimeInfo = {};
callBackTimeInfo.requestStartTime = Date.now();
callBackData.timeInfo = callBackTimeInfo;
//跟隨請求保存回調信息點
request.setImageKnifeData(callBackData);
}
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void { enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
//初始化加载回调信息
this.initCallData(request);
//1.内存有的话直接渲染 //1.内存有的话直接渲染
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) { if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
return return
@ -129,7 +191,7 @@ export class ImageKnifeDispatcher {
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void { getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void {
LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:" + currentRequest.imageKnifeOption.loadSrc)
if (requestSource === ImageKnifeRequestSource.SRC && currentRequest.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { if (requestSource === ImageKnifeRequestSource.SRC && currentRequest.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
currentRequest.imageKnifeOption.onLoadListener?.onLoadStart() currentRequest.imageKnifeOption.onLoadListener?.onLoadStart(currentRequest)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc)
} }
@ -152,7 +214,7 @@ export class ImageKnifeDispatcher {
// 回调请求开始 // 回调请求开始
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart() requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart(requestWithSource.request)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc)
} }
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) { if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
@ -272,6 +334,12 @@ export class ImageKnifeDispatcher {
if (requestJobResult === undefined){ if (requestJobResult === undefined){
return return
} }
//设置请求结束的时间
if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) {
requestJobResult.imageKnifeData.timeInfo.requestEndTime = Date.now();
}
let pixelmap = requestJobResult.pixelMap; let pixelmap = requestJobResult.pixelMap;
if (pixelmap === undefined) { if (pixelmap === undefined) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc)
@ -280,6 +348,7 @@ export class ImageKnifeDispatcher {
if (requestWithSource.source === ImageKnifeRequestSource.SRC && if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined &&
requestJobResult.loadFail) { requestJobResult.loadFail) {
this.assembleImageKnifeData(requestWithSource.request.getImageKnifeData(), requestJobResult.imageKnifeData, requestWithSource.request)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request); requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc)
} }
@ -304,12 +373,19 @@ export class ImageKnifeDispatcher {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc)
} }
let ImageKnifeData: ImageKnifeData = { let imageKnifeData: ImageKnifeData;
if (!requestJobResult.imageKnifeData) {
imageKnifeData = {
source: pixelmap!, source: pixelmap!,
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width, imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height, imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
type:requestJobResult.type type: requestJobResult.type,
}; };
} else {
imageKnifeData = requestJobResult.imageKnifeData;
imageKnifeData.source = pixelmap!;
}
if(requestJobResult.pixelMapList != undefined) { if(requestJobResult.pixelMapList != undefined) {
let imageAnimator: Array<ImageFrameInfo> = [] let imageAnimator: Array<ImageFrameInfo> = []
requestJobResult.pixelMapList.forEach((item,index)=>{ requestJobResult.pixelMapList.forEach((item,index)=>{
@ -318,14 +394,24 @@ export class ImageKnifeDispatcher {
duration:requestJobResult.delayList![index] duration:requestJobResult.delayList![index]
}) })
}) })
ImageKnifeData.imageAnimator = imageAnimator imageKnifeData.imageAnimator = imageAnimator
} }
//构建缓存保存的ImageKnifeData
let saveCacheImageData: ImageKnifeData = {
source: pixelmap!,
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
type: requestJobResult.type,
imageAnimator: imageKnifeData.imageAnimator
}
// 保存内存缓存 // 保存内存缓存
if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) { if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc)
ImageKnife.getInstance() ImageKnife.getInstance()
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator), .saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator),
ImageKnifeData); saveCacheImageData);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
} }
if (requestList !== undefined) { if (requestList !== undefined) {
@ -339,7 +425,7 @@ export class ImageKnifeDispatcher {
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) { requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc)
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
ImageKnifeData.source, requestWithSource.source,ImageKnifeData.imageAnimator); imageKnifeData.source, requestWithSource.source,imageKnifeData.imageAnimator);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc)
} }
@ -348,7 +434,9 @@ export class ImageKnifeDispatcher {
if (requestWithSource.request.imageKnifeOption.onLoadListener && if (requestWithSource.request.imageKnifeOption.onLoadListener &&
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) { requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
// 回调请求成功 // 回调请求成功
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(ImageKnifeData.source,ImageKnifeData); this.assembleImageKnifeData(requestWithSource.request.getImageKnifeData(), imageKnifeData,requestWithSource.request);
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source,
imageKnifeData, requestWithSource.request);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc)
} }
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) { } else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
@ -357,7 +445,19 @@ export class ImageKnifeDispatcher {
} else { } else {
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) { if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
// 回调请求成功 // 回调请求成功
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") // 回调请求成功
//设置失败回调的时间点
let callBackData = requestWithSource.request.getImageKnifeData();
if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) {
requestJobResult.imageKnifeData.timeInfo.requestCancelTime = Date.now();
if (requestJobResult.imageKnifeData.errorInfo) {
requestJobResult.imageKnifeData.errorInfo.phase = LoadPhase.PHASE_WILL_SHOW;
requestJobResult.imageKnifeData.errorInfo.code = LoadPixelMapCode.IMAGE_LOAD_CANCEL_FAILED_CODE;
}
}
this.assembleImageKnifeData(callBackData,requestJobResult.imageKnifeData,requestWithSource.request)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed", requestWithSource.request)
} }
} }
}); });
@ -385,7 +485,19 @@ export class ImageKnifeDispatcher {
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc)
break break
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) { }else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") //构建回调错误信息
let callBackData = request.getImageKnifeData();
if (callBackData) {
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData)
timeInfo.requestCancelTime = Date.now();
timeInfo.requestEndTime = Date.now()
let errorInfo: ErrorInfo = {
phase: LoadPhase.PHASE_THREAD_QUEUE,
code: LoadPixelMapCode.IMAGE_LOAD_CANCEL_FAILED_CODE,
};
callBackData.errorInfo = errorInfo;
}
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed", request)
} }
} }
} }

View File

@ -14,12 +14,16 @@
*/ */
import { import {
CacheStrategy, CacheStrategy,
DecodeImageInfo,
ErrorInfo,
ImageKnifeData,
ImageKnifeRequestSource, ImageKnifeRequestSource,
ImageKnifeRequestWithSource, RequestJobRequest } from './model/ImageKnifeData'; ImageKnifeRequestWithSource, RequestJobRequest,
TimeInfo } from './model/ImageKnifeData';
import List from '@ohos.util.List' import List from '@ohos.util.List'
import { FileCache } from './cache/FileCache'; import { FileCache } from './cache/FileCache';
import { LogUtil } from './utils/LogUtil'; import { LogUtil } from './utils/LogUtil';
import { Constants } from './utils/Constants'; import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants';
import http from '@ohos.net.http'; import http from '@ohos.net.http';
import { combineArrayBuffers } from './utils/ArrayBufferUtils'; import { combineArrayBuffers } from './utils/ArrayBufferUtils';
import { BusinessError } from '@kit.BasicServicesKit'; import { BusinessError } from '@kit.BasicServicesKit';
@ -43,58 +47,94 @@ export class ImageKnifeLoader {
ImageKnifeLoader.getImageArrayBuffer(request,requestList,fileKey) ImageKnifeLoader.getImageArrayBuffer(request,requestList,fileKey)
} }
static async parseImage(resBuf: ArrayBuffer, fileKey: string, static async parseImage(resBuf: ArrayBuffer, fileKey: string,
request: RequestJobRequest) { request: RequestJobRequest, callBackData: ImageKnifeData) {
callBackData.bufSize = resBuf.byteLength;
let typeValue = new FileTypeUtil().getFileType(resBuf); let typeValue = new FileTypeUtil().getFileType(resBuf);
if(typeValue == null) { if(typeValue == null) {
LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src) LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src)
ImageKnifeLoader.makeEmptyResult(request,"request is not a valid image source") ImageKnifeLoader.makeEmptyResult(request,"request is not a valid image source", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT, LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE))
return return
} }
callBackData.type = typeValue;
if(request.isAnimator) { if(request.isAnimator) {
ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request) ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request, callBackData)
return return
} }
if (typeValue === 'gif' || typeValue === 'webp') { if (typeValue === 'gif' || typeValue === 'webp') {
ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request) ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request, callBackData)
return return
} else if(typeValue == "svg") { } else if(typeValue == "svg") {
ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request) ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request, callBackData)
return return
} }
ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request) ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request, callBackData)
} }
static makeEmptyResult(request:RequestJobRequest,error: string){ static makeEmptyResult(request:RequestJobRequest,error: string, data?: ImageKnifeData){
let res: RequestJobResult = { let res: RequestJobResult = {
pixelMap: undefined, pixelMap: undefined,
bufferSize: 0, bufferSize: 0,
fileKey: '', fileKey: '',
loadFail: error, loadFail: error,
imageKnifeData: data
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } }) emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} }
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest) { static assembleError(data: ImageKnifeData | undefined, phase: string, code?: number,
httpCode?: number): ImageKnifeData | undefined {
let errorCallBackData = data?.errorInfo;
if (!errorCallBackData) {
return data;
}
errorCallBackData.phase = phase;
errorCallBackData.code = code? code: 0;
if (httpCode && httpCode != 0) {
errorCallBackData.httpCode = httpCode;
}
return data
}
static getTimeInfo(callBackData: ImageKnifeData): TimeInfo {
let timeInfo: TimeInfo;
if (callBackData.timeInfo) {
timeInfo = callBackData.timeInfo;
}else {
timeInfo = {};
callBackData.timeInfo = timeInfo;
}
return timeInfo;
}
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest, callBackData: ImageKnifeData) {
let resPixelmap: PixelMap | undefined = undefined let resPixelmap: PixelMap | undefined = undefined
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
let decodingOptions: image.DecodingOptions = { let decodingOptions: image.DecodingOptions = {
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false, editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
} }
let imageSource: image.ImageSource = image.createImageSource(resBuf) let imageSource: image.ImageSource = image.createImageSource(resBuf)
if (imageSource === undefined){ if (imageSource === undefined){
ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return return
} }
let size = (await imageSource.getImageInfo()).size let size = (await imageSource.getImageInfo()).size
callBackData.imageWidth = size.width;
callBackData.imageHeight = size.height;
timeInfo.decodeStartTime = Date.now();
await imageSource.createPixelMap(decodingOptions) await imageSource.createPixelMap(decodingOptions)
.then((pixelmap: PixelMap) => { .then((pixelmap: PixelMap) => {
timeInfo.decodeEndTime = Date.now();
resPixelmap = pixelmap resPixelmap = pixelmap
imageSource.release() imageSource.release()
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
timeInfo.decodeEndTime = Date.now();
imageSource.release() imageSource.release()
ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error)) ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_PIXEL_MAP, LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE))
return return
}) })
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) { if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) {
@ -107,21 +147,38 @@ export class ImageKnifeLoader {
} catch (e) { } catch (e) {
LogUtil.error("PixelMap setTransferDetached err:"+JSON.stringify(e)) LogUtil.error("PixelMap setTransferDetached err:"+JSON.stringify(e))
} }
//获取各个pixelMap的大小
if (resPixelmap && typeof resPixelmap !== "string") {
let decodeImages: Array<DecodeImageInfo> = [];
let size = (resPixelmap as PixelMap).getImageInfoSync().size;
let decodeImage: DecodeImageInfo = {
contentWidth: size.width,
contentHeight: size.height,
contentSize: (resPixelmap as PixelMap).getPixelBytesNumber()
}
decodeImages.push(decodeImage);
callBackData.decodeImages = decodeImages;
}
let res: RequestJobResult = { let res: RequestJobResult = {
pixelMap: resPixelmap, pixelMap: resPixelmap,
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
size:size, size:size,
type:typeValue type:typeValue,
imageKnifeData:callBackData
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } }) emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} }
static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
request: RequestJobRequest) { request: RequestJobRequest, callBackData: ImageKnifeData) {
let resPixelmap: PixelMap | undefined = undefined let resPixelmap: PixelMap | undefined = undefined
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
let imageSource: image.ImageSource = image.createImageSource(resBuf) let imageSource: image.ImageSource = image.createImageSource(resBuf)
if (imageSource === undefined){ if (imageSource === undefined){
ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return return
} }
@ -129,6 +186,9 @@ export class ImageKnifeLoader {
let scale = size.height / size.width let scale = size.height / size.width
let hValue = Math.round(request.componentHeight); let hValue = Math.round(request.componentHeight);
let wValue = Math.round(request.componentWidth); let wValue = Math.round(request.componentWidth);
callBackData.imageWidth = size.width;
callBackData.imageHeight = size.height;
timeInfo.decodeStartTime = Date.now();
let defaultSize: image.Size = { let defaultSize: image.Size = {
height: vp2px(wValue) * scale, height: vp2px(wValue) * scale,
width: vp2px(wValue) width: vp2px(wValue)
@ -139,6 +199,7 @@ export class ImageKnifeLoader {
}; };
await imageSource.createPixelMap(opts) await imageSource.createPixelMap(opts)
.then((pixelmap: PixelMap) => { .then((pixelmap: PixelMap) => {
timeInfo.decodeEndTime = Date.now();
resPixelmap = pixelmap resPixelmap = pixelmap
imageSource.release() imageSource.release()
try { try {
@ -147,59 +208,88 @@ export class ImageKnifeLoader {
LogUtil.error("PixelMap setTransferDetached err:"+JSON.stringify(e)) LogUtil.error("PixelMap setTransferDetached err:"+JSON.stringify(e))
} }
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
timeInfo.decodeEndTime = Date.now();
imageSource.release() imageSource.release()
ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error)) ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_PIXEL_MAP, LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE))
return return
}) })
//获取各个pixelMap的大小
if (resPixelmap && typeof resPixelmap !== "string") {
let decodeImages: Array<DecodeImageInfo> = [];
let decodeImage: DecodeImageInfo = {
contentWidth: defaultSize.width,
contentHeight: defaultSize.height,
contentSize: (resPixelmap as PixelMap).getPixelBytesNumber()
}
decodeImages.push(decodeImage);
}
let res: RequestJobResult = { let res: RequestJobResult = {
pixelMap: resPixelmap, pixelMap: resPixelmap,
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
type:typeValue type:typeValue,
imageKnifeData:callBackData
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } }) emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} }
static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string, static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string,
fileKey: string,request: RequestJobRequest) { fileKey: string,request: RequestJobRequest, callBackData: ImageKnifeData) {
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
let imageSource: image.ImageSource = image.createImageSource(resBuf) let imageSource: image.ImageSource = image.createImageSource(resBuf)
if (imageSource === undefined){ if (imageSource === undefined){
ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CREATE_SOURCE,LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return return
} }
let frameCount = await imageSource.getFrameCount() let frameCount = await imageSource.getFrameCount()
let size = (await imageSource.getImageInfo()).size let size = (await imageSource.getImageInfo()).size
callBackData.frameCount = frameCount;
callBackData.imageWidth = size.width;
callBackData.imageHeight = size.height;
imageSource.release() imageSource.release()
if(frameCount == undefined || frameCount == 1) { if(frameCount == undefined || frameCount == 1) {
} else { } else {
timeInfo.decodeStartTime = Date.now()
let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf)) let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf))
timeInfo.diskCheckEndTime = Date.now()
let res: RequestJobResult = { let res: RequestJobResult = {
pixelMap: base64str, pixelMap: base64str,
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
size:size, size:size,
type:typeValue type:typeValue,
imageKnifeData:callBackData
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } }) emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
return return
} }
ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request) ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request, callBackData)
} }
// 为AnimatorComponent解析动图 // 为AnimatorComponent解析动图
static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest) { static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest, callBackData: ImageKnifeData) {
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
if (typeValue === 'gif' || typeValue === 'webp') { if (typeValue === 'gif' || typeValue === 'webp') {
let imageSource: image.ImageSource = image.createImageSource(resBuf); let imageSource: image.ImageSource = image.createImageSource(resBuf);
if (imageSource === undefined){ if (imageSource === undefined){
ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return return
} }
let decodingOptions: image.DecodingOptions = { let decodingOptions: image.DecodingOptions = {
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false, editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
} }
callBackData.imageWidth = imageSource.getImageInfoSync().size.width;
callBackData.imageHeight = imageSource.getImageInfoSync().size.height;
let pixelMapList: Array<PixelMap> = [] let pixelMapList: Array<PixelMap> = []
let delayList: Array<number> = [] let delayList: Array<number> = []
timeInfo.decodeStartTime = Date.now();
let decodeImages: Array<DecodeImageInfo> = [];
await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => { await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => {
timeInfo.decodeEndTime = Date.now();
//sdk的api接口发生变更从.getDelayTime() 变为.getDelayTimeList() //sdk的api接口发生变更从.getDelayTime() 变为.getDelayTimeList()
await imageSource.getDelayTimeList().then(delayTimes => { await imageSource.getDelayTimeList().then(delayTimes => {
if (pixelList.length > 0) { if (pixelList.length > 0) {
@ -210,26 +300,37 @@ export class ImageKnifeLoader {
} else { } else {
delayList.push(delayTimes[delayTimes.length - 1]) delayList.push(delayTimes[delayTimes.length - 1])
} }
//获取各个pixelMap的大小
let size = pixelList[i].getImageInfoSync().size
let decodeImage: DecodeImageInfo = {
contentWidth: size.width,
contentHeight: size.height,
contentSize: pixelList[i].getPixelBytesNumber()
}
decodeImages.push(decodeImage);
} }
imageSource.release(); imageSource.release();
} }
}) })
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
imageSource.release() imageSource.release()
ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error)) timeInfo.decodeEndTime = Date.now();
ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CREATE_PIXEL_MAP,LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE))
return return
}) })
callBackData.decodeImages = decodeImages;
let res: RequestJobResult = { let res: RequestJobResult = {
pixelMap: "", pixelMap: "",
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
type: typeValue, type: typeValue,
imageKnifeData:callBackData,
pixelMapList, pixelMapList,
delayList delayList
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } }) emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} else { } else {
ImageKnifeLoader.makeEmptyResult(request,"ImageKnifeAnimatorComponent组件仅支持动态图") ImageKnifeLoader.makeEmptyResult(request,"ImageKnifeAnimatorComponent组件仅支持动态图", ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_PARSE_IAMGE,LoadPixelMapCode.IMAGE_FORMAT_ERROR_CODE))
} }
} }
static getHeaderObj(request:RequestJobRequest){ static getHeaderObj(request:RequestJobRequest){
@ -245,23 +346,39 @@ export class ImageKnifeLoader {
} }
return headerObj return headerObj
} }
static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string){ static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string, callBackData: ImageKnifeData){
// 保存文件缓存 // 保存文件缓存
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) { if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src) LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder) FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src) LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
} }
ImageKnifeLoader.parseImage(resBuf,fileKey,request) ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
} }
// 获取图片资源 // 获取图片资源
static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string) { static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string) {
let resBuf: ArrayBuffer | undefined let resBuf: ArrayBuffer | undefined
let loadError: string = "" let loadError: string = ""
//定义图片各个阶段错误信息
let error: ErrorInfo = { code: 0, phase: LoadPhase.PHASE_LOAD }
//定义加载时间点
let callBackTimeInfo: TimeInfo = {};
//定义加载信息回调数据
let callBackData: ImageKnifeData = {
source: "",
imageWidth: 0,
imageHeight: 0,
timeInfo: callBackTimeInfo,
errorInfo: error
};
// 判断自定义下载 // 判断自定义下载
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") { if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") {
// 先从文件缓存获取 // 先从文件缓存获取
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CUSTOM_LOAD)
callBackTimeInfo.diskCheckStartTime = Date.now();
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
callBackTimeInfo.diskCheckEndTime = Date.now();
if (resBuf === undefined) { if (resBuf === undefined) {
LogUtil.log("start customGetImage src=" + request.src) LogUtil.log("start customGetImage src=" + request.src)
const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request) const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request)
@ -269,17 +386,17 @@ export class ImageKnifeLoader {
request.customGetImage(request.context, request.src, headerObj) request.customGetImage(request.context, request.src, headerObj)
.then((buffer)=>{ .then((buffer)=>{
if(buffer != undefined) { if(buffer != undefined) {
ImageKnifeLoader.FileCacheParseImage(request,buffer,fileKey) ImageKnifeLoader.FileCacheParseImage(request,buffer,fileKey,callBackData)
} else { } else {
loadError = "customGetImage loadFail undefined" loadError = "customGetImage loadFail undefined"
ImageKnifeLoader.makeEmptyResult(request,loadError) ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
} }
}).catch((err:string)=>{ }).catch((err:string)=>{
ImageKnifeLoader.makeEmptyResult(request,err) ImageKnifeLoader.makeEmptyResult(request,err, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
}) })
} catch (e) { } catch (e) {
loadError = "customGetImage loadFail failed" loadError = "customGetImage loadFail failed"
ImageKnifeLoader.makeEmptyResult(request,loadError + e) 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.src)
return return
@ -289,12 +406,16 @@ export class ImageKnifeLoader {
if (typeof request.src === 'string') { if (typeof request.src === 'string') {
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载 if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
// 先从文件缓存获取 // 先从文件缓存获取
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET)
callBackTimeInfo.diskCheckStartTime = Date.now()
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
callBackTimeInfo.diskCheckEndTime = Date.now()
if (resBuf !== undefined){ 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.src)
} }
else if (request.onlyRetrieveFromCache != true) { else if (request.onlyRetrieveFromCache != true) {
LogUtil.log("HttpDownloadClient.start:" + request.src) LogUtil.log("HttpDownloadClient.start:" + request.src)
callBackTimeInfo.netRequestStartTime = Date.now();
let httpRequest = http.createHttp(); let httpRequest = http.createHttp();
let progress: number = 0 let progress: number = 0
let arrayBuffers = new Array<ArrayBuffer>() let arrayBuffers = new Array<ArrayBuffer>()
@ -336,24 +457,29 @@ export class ImageKnifeLoader {
}); });
promise.then((data: number) => { promise.then((data: number) => {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, undefined, data)
callBackTimeInfo.netRequestEndTime = Date.now();
if (data == 200 || data == 206 || data == 204) { if (data == 200 || data == 206 || data == 204) {
resBuf = combineArrayBuffers(arrayBuffers) resBuf = combineArrayBuffers(arrayBuffers)
ImageKnifeLoader.FileCacheParseImage(request,resBuf,fileKey) ImageKnifeLoader.FileCacheParseImage(request,resBuf,fileKey, callBackData)
} else { } else {
loadError = "HttpDownloadClient has error, http code =" + JSON.stringify(data) loadError = "HttpDownloadClient has error, http code =" + JSON.stringify(data)
ImageKnifeLoader.makeEmptyResult(request,loadError) ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE, data))
} }
}).catch((err: Error) => { }).catch((err: Error) => {
loadError = "HttpDownloadClient download ERROR : err = " + JSON.stringify(err) loadError = "HttpDownloadClient download ERROR : err = " + JSON.stringify(err)
ImageKnifeLoader.makeEmptyResult(request,loadError) 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.src)
return return
} }
else { else {
callBackTimeInfo.netRequestEndTime = Date.now();
loadError = 'onlyRetrieveFromCache,do not fetch image src = ' + request.src loadError = 'onlyRetrieveFromCache,do not fetch image src = ' + request.src
} }
} else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) { } else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE)
await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => { await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => {
await fs.stat(file.fd).then(async (stat) =>{ await fs.stat(file.fd).then(async (stat) =>{
let buf = new ArrayBuffer(stat.size); let buf = new ArrayBuffer(stat.size);
@ -361,15 +487,19 @@ export class ImageKnifeLoader {
resBuf = buf; resBuf = buf;
fs.closeSync(file.fd); fs.closeSync(file.fd);
}).catch((err:BusinessError) => { }).catch((err:BusinessError) => {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE)
loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code
}) })
}).catch((err:BusinessError) => { }).catch((err:BusinessError) => {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE)
loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code
}) })
}).catch((err:BusinessError) => { }).catch((err:BusinessError) => {
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 loadError = 'LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code
}) })
} else { //从本地文件获取 } else { //从本地文件获取
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE)
try { try {
let stat = fs.statSync(request.src); let stat = fs.statSync(request.src);
if (stat.size > 0) { if (stat.size > 0) {
@ -379,6 +509,7 @@ export class ImageKnifeLoader {
fs.closeSync(file); fs.closeSync(file);
} }
} catch (err) { } catch (err) {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE, LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE)
loadError = err loadError = err
} }
} }
@ -403,9 +534,10 @@ export class ImageKnifeLoader {
} }
if (resBuf === undefined){ if (resBuf === undefined){
ImageKnifeLoader.makeEmptyResult(request,loadError) callBackTimeInfo.requestEndTime = Date.now();
ImageKnifeLoader.makeEmptyResult(request,loadError ,callBackData)
return return
} }
ImageKnifeLoader.parseImage(resBuf,fileKey,request) ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
} }
} }

View File

@ -20,12 +20,53 @@ import common from '@ohos.app.ability.common';
import { Size } from '@kit.ArkUI' import { Size } from '@kit.ArkUI'
export interface ImageKnifeData { export interface ImageKnifeData {
source: PixelMap | string, source: PixelMap | string, // url
imageWidth: number, imageWidth: number, // 原始宽高大小
imageHeight: number, imageHeight: number,
bufSize?: number, // 图片的字节数
type?:string, type?:string,
imageAnimator?: Array<ImageFrameInfo> imageAnimator?: Array<ImageFrameInfo>
frameCount ?: number // 帧
decodeImages?: Array<DecodeImageInfo> //Image组件或者ImageAnimator组件可以加载一张或者多张
timeInfo?: TimeInfo // 加载图片的各个时间点
errorInfo?: ErrorInfo // 错误
} }
/**
* 解码后的图片的size
*/
export interface DecodeImageInfo {
contentWidth ?: number // 解码后宽高
contentHeight?: number
contentSize ?: number // 大小
}
/**
* 加载的错误信息
*/
export interface ErrorInfo {
phase: string, //图片加载阶段信息,如:网络加载阶段,缓存获取阶段及其解码阶段等
code: number,
httpCode?: number
}
/**
* load检查时间点
*/
export interface TimeInfo {
requestStartTime?: number,
requestEndTime?: number,
requestCancelTime?: number,
memoryCheckStartTime?: number,
memoryCheckEndTime?: number,
diskCheckStartTime?: number,
diskCheckEndTime?: number,
netRequestStartTime?: number,
netRequestEndTime?: number,
decodeStartTime?: number,
decodeEndTime?: number,
}
/** /**
* onComplete成功回调 * onComplete成功回调
*/ */
@ -78,7 +119,8 @@ export interface RequestJobResult {
size?:Size, size?:Size,
type?: string, type?: string,
pixelMapList?:Array<PixelMap>, pixelMapList?:Array<PixelMap>,
delayList?: Array<number> delayList?: Array<number>,
imageKnifeData?: ImageKnifeData,
} }
/** /**

View File

@ -84,13 +84,13 @@ export class ImageKnifeOption {
*/ */
export interface OnLoadCallBack { export interface OnLoadCallBack {
// 请求开始 // 请求开始
onLoadStart?: () => void; onLoadStart?: (request?: ImageKnifeRequest) => void;
// 请求成功 // 请求成功
onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData) => void; onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData, request?: ImageKnifeRequest) => void;
// 请求结束 // 请求结束
onLoadFailed?: (err: string,request?: ImageKnifeRequest) => void; onLoadFailed?: (err: string, request?: ImageKnifeRequest) => void;
// 请求取消 // 请求取消
onLoadCancel?: (reason: string) => void; onLoadCancel?: (reason: string, request?: ImageKnifeRequest) => void;
} }

View File

@ -14,7 +14,7 @@
*/ */
import { ImageKnifeOption } from './ImageKnifeOption'; import { ImageKnifeOption } from './ImageKnifeOption';
import common from '@ohos.app.ability.common'; import common from '@ohos.app.ability.common';
import { ImageKnifeRequestSource } from './ImageKnifeData'; import { ImageKnifeData, ImageKnifeRequestSource } from './ImageKnifeData';
export class ImageKnifeRequest { export class ImageKnifeRequest {
@ -27,6 +27,7 @@ export class ImageKnifeRequest {
ImageKnifeRequestCallback: ImageKnifeRequestCallback ImageKnifeRequestCallback: ImageKnifeRequestCallback
componentVersion: number = 0 componentVersion: number = 0
headers: Map<string,Object> = new Map<string,Object>() headers: Map<string,Object> = new Map<string,Object>()
private imageCallBackData: ImageKnifeData | undefined = undefined;
constructor(option: ImageKnifeOption, constructor(option: ImageKnifeOption,
uIAbilityContext: common.UIAbilityContext, uIAbilityContext: common.UIAbilityContext,
width: number, width: number,
@ -53,6 +54,14 @@ export class ImageKnifeRequest {
} }
}) })
} }
setImageKnifeData(data: ImageKnifeData) {
this.imageCallBackData = data;
}
getImageKnifeData(): ImageKnifeData | undefined {
return this.imageCallBackData
}
} }
export enum ImageKnifeRequestState { export enum ImageKnifeRequestState {

View File

@ -16,3 +16,59 @@ export class Constants {
public static PROGRESS_EMITTER: string = "progressEmitter" public static PROGRESS_EMITTER: string = "progressEmitter"
public static CALLBACK_EMITTER: string = "callBackEmitter" public static CALLBACK_EMITTER: string = "callBackEmitter"
} }
/**
* 图片加载的code
*/
export enum LoadPixelMapCode {
// createImageSource error code
IMAGE_SOURCE_ERROR_CODE = 100001,
// createPixelMap error code
IMAGE_DECODE_ERROR_CODE = 100002,
//ImageKnifeAnimatorComponent组件仅支持动态图 code
IMAGE_FORMAT_ERROR_CODE = 100003,
//load failed code
IMAGE_LOAD_FAILED_CODE = 100004,
//自定义下载失败 code
IMAGE_CUSTOM_LOAD_FAILED_CODE = 100005,
// http请求失败 code
IMAGE_HTTPS_LOAD_FAILED_CODE = 100006,
//设置onlyRetrieveFromCache 导致的加载失败的code
IMAGE_RETRIEVE_CACHE_CODE = 100007,
//加载共享图片失败code
IMAGE_LOAD_SHARE_FILE_FAILED_CODE = 100008,
//加载本地文件图片失败code
IMAGE_LOAD_LOCAL_FILE_FAILED_CODE = 100009,
// 取消请求加载code
IMAGE_LOAD_CANCEL_FAILED_CODE = 1000010,
// 解析图片格式阶段
IMAGE_PARSE_FORMAT_FAILED_CODE = 1000011
}
/**
* 图片加载的各个阶段
*/
export enum LoadPhase {
// 图片加载阶段
PHASE_LOAD = "load",
// 网络请求下载阶段
PHASE_NET = "net",
//获取图片格式阶段
PHASE_GET_FORMAT = "parse_format",
//自定义下载阶段 customGetImage
PHASE_CUSTOM_LOAD = "customGetImage",
// createPixelMap 阶段
PHASE_CREATE_SOURCE = "createImageSource",
//createPixelMap 阶段
PHASE_CREATE_PIXEL_MAP = "createPixelMap",
//请求队列排队阶段
PHASE_THREAD_QUEUE = "thread_queue",
//图片解析阶段
PHASE_PARSE_IAMGE = "parseImage",
//加载解析datashare:// 或者file:// 阶段
PHASE_SHARE_FILE = "datashare_or_file",
//加载解析本地文件阶段
PHASE_LOCAL_FILE = "load_local_file",
//图片加载解析完成,即将显示的阶段
PHASE_WILL_SHOW = "will_show",
}