ImageKnife/library/src/main/ets/ImageKnifeDispatcher.ets

571 lines
28 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 { ImageKnifeRequest, ImageKnifeRequestState } from './model/ImageKnifeRequest'
import { DefaultJobQueue } from './queue/DefaultJobQueue'
import { IJobQueue } from './queue/IJobQueue'
import List from '@ohos.util.List';
import LightWeightMap from '@ohos.util.LightWeightMap';
import { LogUtil } from './utils/LogUtil';
import { ImageKnife } from './ImageKnife';
import { ImageKnifeData, CacheStrategy, TimeInfo, ErrorInfo } from './model/ImageKnifeData';
import image from '@ohos.multimedia.image';
import emitter from '@ohos.events.emitter';
import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants';
import taskpool from '@ohos.taskpool';
import { IEngineKey } from './key/IEngineKey';
import { DefaultEngineKey } from './key/DefaultEngineKey';
import {
ImageKnifeRequestWithSource,
ImageKnifeRequestSource,
RequestJobResult,
RequestJobRequest
} from './model/ImageKnifeData'
import { BusinessError } from '@kit.BasicServicesKit';
import { ImageKnifeLoader } from './ImageKnifeLoader'
import { DownsampleStrategy } from './downsampling/DownsampleStartegy';
export class ImageKnifeDispatcher {
// 最大并发
private maxRequests: number = 8
// 排队队列
private jobQueue: IJobQueue = new DefaultJobQueue()
// 执行中的请求
executingJobMap: LightWeightMap<string, List<ImageKnifeRequestWithSource>> = new LightWeightMap();
// 开发者可配置全局缓存
private engineKey: IEngineKey = new DefaultEngineKey();
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean {
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') {
memoryCache = {
source: request.imageKnifeOption.loadSrc as image.PixelMap,
imageWidth: 0,
imageHeight: 0,
}
} else {
memoryCache = ImageKnife.getInstance()
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator, request.componentWidth, request.componentHeight));
}
//记录ImageKnifeRequestSource.SRC 开始内存检查的时间点
if (requestSource == ImageKnifeRequestSource.SRC && request.imageKnifeData) {
let timeInfo = request.imageKnifeData?.timeInfo
if (timeInfo) {
timeInfo.memoryCheckStartTime = memoryCheckStartTime;
timeInfo.memoryCheckEndTime = Date.now();
//设置请求结束的时间点
if (memoryCache !== undefined) {
timeInfo.requestEndTime = Date.now();
}
}
}
if (memoryCache !== undefined) {
// 画主图
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
// 回调请求开始
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
request.imageKnifeOption.onLoadListener.onLoadStart(request)
LogUtil.log('MemoryCache_onLoadStart:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion)
}
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('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('MemoryCache_onLoadSuccess:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion)
}
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
request.requestState = ImageKnifeRequestState.ERROR
}
}
LogUtil.log('showFromMemomry.end_hasmemory:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion)
return true
}
LogUtil.log('showFromMemomry.end_nomemory:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion)
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.imageKnifeData = 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.imageKnifeData = callBackData;
}
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
//初始化加载回调信息
this.initCallData(request);
//1.内存有的话直接渲染
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
return
}
// 2.内存获取占位图
if (request.imageKnifeOption.placeholderSrc !== undefined) {
if (this.showFromMemomry(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)) {
request.drawPlayHolderSuccess = true
}
}
//3.判断是否要排队
if (this.executingJobMap.length >= this.maxRequests) {
this.jobQueue.add(request)
return
}
this.executeJob(request,isAnimator)
}
executeJob(request: ImageKnifeRequest,isAnimator?: boolean): void {
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)
}
// 加载主图
this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)
LogUtil.log('executeJob.end:' + request.componentId + ',version:' + request.componentVersion)
}
/**
* 获取和显示图片
*/
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void {
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('getAndShowImage_onLoadStart:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator, currentRequest.componentWidth, currentRequest.componentHeight)
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
if (requestList == undefined) {
requestList = new List()
requestList.add({ request: currentRequest, source: requestSource })
this.executingJobMap.set(memoryKey, requestList)
} else {
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
}
let src: string | number = ''
let moduleName: string = ''
let resName: string = ''
if((imageSrc as Resource).id != undefined) {
moduleName = (imageSrc as Resource).moduleName
src = (imageSrc as Resource).id
if(src == -1) {
resName = (imageSrc as Resource).params![0]
}
} else if(typeof imageSrc == 'string') {
src = imageSrc
}
let request: RequestJobRequest = {
context: currentRequest.context,
src: src,
headers: currentRequest.imageKnifeOption.headerOption,
allHeaders: currentRequest.headers,
componentWidth:currentRequest.componentWidth,
componentHeight:currentRequest.componentHeight,
customGetImage: currentRequest.imageKnifeOption.customGetImage,
onlyRetrieveFromCache: currentRequest.imageKnifeOption.onlyRetrieveFromCache,
transformation: currentRequest.imageKnifeOption.transformation,
writeCacheStrategy: ImageKnife.getInstance()
.isFileCacheInit() ? currentRequest.imageKnifeOption.writeCacheStrategy : CacheStrategy.Memory, // 未初始化文件缓存时,不写文件缓存
engineKey: this.engineKey,
signature: currentRequest.imageKnifeOption.signature,
requestSource: requestSource,
isWatchProgress: isWatchProgress,
memoryKey: memoryKey,
fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(),
isAnimator:isAnimator,
moduleName: moduleName == '' ? undefined : moduleName,
resName: resName == '' ? undefined : resName,
caPath: currentRequest.imageKnifeOption.httpOption?.caPath,
targetWidth: currentRequest.componentWidth,
targetHeight: currentRequest.componentHeight,
downsampType: currentRequest.imageKnifeOption.downsampleOf == undefined ? DownsampleStrategy.DEFAULT : currentRequest.imageKnifeOption.downsampleOf,
isAutoImageFit: currentRequest.imageKnifeOption.objectFit == ImageFit.Auto,
componentId: currentRequest.componentId,
componentVersion: currentRequest.componentVersion,
connectTimeout: currentRequest.imageKnifeOption.httpOption?.connectTimeout,
readTimeout: currentRequest.imageKnifeOption.httpOption?.readTimeout
}
if(request.customGetImage == undefined) {
request.customGetImage = ImageKnife.getInstance().getCustomGetImage()
}
emitter.on(Constants.CALLBACK_EMITTER + memoryKey,(data)=>{
emitter.off(Constants.CALLBACK_EMITTER + memoryKey)
let res = data?.data?.value as RequestJobResult | undefined
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
if (isWatchProgress){
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
}
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('etAndShowImage_Task.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
let task = new taskpool.Task(requestJob, request)
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('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('getAndShowImage.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
if (isWatchProgress){
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
}
this.doTaskCallback({
pixelMap: undefined,
bufferSize: 0,
fileKey: '',
loadFail: 'Fail to requestJob in sub thread src=' + imageSrc + ' err=' + err,
imageKnifeData: {
source: '',
imageWidth: 0,
imageHeight: 0,
timeInfo: { requestEndTime: Date.now() },
errorInfo: {
phase: LoadPhase.PHASE_LOAD,
code: LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE,
}
}
}, requestList!, currentRequest, memoryKey, imageSrc, requestSource, isAnimator)
})
} else { //主线程请求
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('getAndShowImage.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
this.doTaskCallback({
pixelMap: undefined,
bufferSize: 0,
fileKey: '',
loadFail: 'Fail to requestJob in main thread src=' + imageSrc + ' err=' + err,
imageKnifeData: {
source: '',
imageWidth: 0,
imageHeight: 0,
timeInfo: { requestEndTime: Date.now() },
errorInfo: {
phase: LoadPhase.PHASE_LOAD,
code: LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE,
}
}
}, requestList!, currentRequest, memoryKey, imageSrc, requestSource, isAnimator)
})
}
}
/**
* 回调下载进度
* @param requestList 请求列表
* @param data 进度
*/
private progressCallBack(requestList:List<ImageKnifeRequestWithSource>, data: number) {
for (let i = 0; i < requestList.length; i++) {
let requestWithSource:ImageKnifeRequestWithSource = requestList[i]
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
requestWithSource.request.imageKnifeOption.progressListener(data)
}
}
}
private doTaskCallback(requestJobResult: RequestJobResult | undefined, requestList: List<ImageKnifeRequestWithSource> ,
currentRequest: ImageKnifeRequest, memoryKey: string, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean):void {
LogUtil.log('getAndShowImage_CallBack.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
if (requestJobResult === undefined){
return
}
//设置请求结束的时间
if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) {
requestJobResult.imageKnifeData.timeInfo.requestEndTime = Date.now();
}
let pixelmap = requestJobResult.pixelMap;
if (pixelmap === undefined) {
this.executingJobMap.remove(memoryKey);
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR
LogUtil.error('getAndShowImage_CallBack.pixelmap failed:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion + " error: " + requestJobResult.loadFail)
// 回调请求失败
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined &&
requestJobResult.loadFail) {
this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, requestJobResult.imageKnifeData, requestWithSource.request)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request);
LogUtil.log('getAndShowImage_onLoadFailed:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
requestWithSource.request.requestState = ImageKnifeRequestState.PROGRESS
if (this.showFromMemomry(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
ImageKnifeRequestSource.ERROR_HOLDER) === false) {
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
ImageKnifeRequestSource.ERROR_HOLDER);
}
}
});
this.dispatchNextJob();
return;
}
// 保存文件缓存
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) {
LogUtil.log('getAndShowImage_saveWithoutWriteFile.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize);
LogUtil.log('getAndShowImage_saveWithoutWriteFile.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
let imageKnifeData: ImageKnifeData;
if (!requestJobResult.imageKnifeData) {
imageKnifeData = {
source: pixelmap!,
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
type: requestJobResult.type,
};
} else {
imageKnifeData = requestJobResult.imageKnifeData;
imageKnifeData.source = pixelmap!;
}
if(requestJobResult.pixelMapList != undefined) {
let imageAnimator: Array<ImageFrameInfo> = []
requestJobResult.pixelMapList.forEach((item,index)=>{
imageAnimator.push({
src:requestJobResult.pixelMapList![index],
duration:requestJobResult.delayList![index]
})
})
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) {
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('getAndShowImage_saveMemoryCache.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
if (requestList !== undefined) {
// key相同的request一起绘制
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
// 画主图
if (requestWithSource.source === ImageKnifeRequestSource.SRC ||
requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
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('getAndShowImage_showPixelMap.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE;
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('getAndShowImage_onLoadSuccess:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
}
} else {
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
// 回调请求成功
// 回调请求成功
//设置失败回调的时间点
let callBackData = requestWithSource.request.imageKnifeData;
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)
LogUtil.log('getAndShowImage cancel:' + requestWithSource.request.componentId + ',srcType:' + requestSource + ',version:' + requestWithSource.request.componentVersion)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', requestWithSource.request)
}
}
});
this.executingJobMap.remove(memoryKey);
this.dispatchNextJob();
} else {
LogUtil.log('error: no requestlist need to draw for key = ' + memoryKey);
}
LogUtil.log('getAndShowImage_CallBack.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
}
dispatchNextJob() {
LogUtil.log('dispatchNextJob.start')
// 主图和错误图并发加载时以及主图加载失败后立即加载错误图可能会导致短时间内并发数超过maxRequests故此处减少响应的并发
if (this.executingJobMap.length >= this.maxRequests) {
return
}
while (true) {
let request = this.jobQueue.pop()
if (request === undefined) {
LogUtil.log('dispatchNextJob.end:no any job')
break // 队列已无任务
}
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
LogUtil.log('dispatchNextJob.start executeJob:' + request.componentId + ',version:' + request.componentVersion)
this.executeJob(request)
LogUtil.log('dispatchNextJob.end executeJob:' + request.componentId + ',version:' + request.componentVersion)
break
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
//构建回调错误信息
let callBackData = request.imageKnifeData;
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;
}
LogUtil.log('dispatchNextJob cancel:' + request.componentId + ',version:' + request.componentVersion)
request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', request)
}
}
}
setMaxRequests(concurrency: number): void {
if (concurrency > 0) {
this.maxRequests = concurrency
}
}
setEngineKeyImpl(impl: IEngineKey): void {
this.engineKey = impl;
}
getEngineKeyImpl(): IEngineKey {
return this.engineKey;
}
}
/**
* 通过taskpool 二级缓存,下载/读取本地文件,编解码
* @param context
* @param src
* @returns
*/
@Concurrent
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>) {
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)
//获取图片资源
ImageKnifeLoader.execute(request,requestList,fileKey)
}