|
|
|
@ -16,7 +16,7 @@
|
|
|
|
|
import { DiskLruCache } from "../cache/DiskLruCache"
|
|
|
|
|
import { EngineKeyFactories } from "../cache/key/EngineKeyFactories"
|
|
|
|
|
import { EngineKeyInterface } from "../cache/key/EngineKeyInterface"
|
|
|
|
|
import { RequestOption } from "../imageknife/RequestOption"
|
|
|
|
|
import { RequestOption, Size } from "../imageknife/RequestOption"
|
|
|
|
|
import { AsyncCallback } from "../imageknife/interface/AsyncCallback"
|
|
|
|
|
import { PlaceHolderManager } from "../imageknife/holder/PlaceHolderManager"
|
|
|
|
|
import { RetryHolderManager } from "../imageknife/holder/RetryHolderManager"
|
|
|
|
@ -42,17 +42,12 @@ import { MemoryLruCache } from '../cache/MemoryLruCache'
|
|
|
|
|
import { BusinessError } from '@kit.BasicServicesKit'
|
|
|
|
|
import { taskpool } from '@kit.ArkTS'
|
|
|
|
|
import { GIFFrame } from './utils/gif/GIFFrame'
|
|
|
|
|
import emitter from '@ohos.events.emitter';
|
|
|
|
|
|
|
|
|
|
import { MemoryCacheProxy } from './requestmanage/MemoryCacheProxy'
|
|
|
|
|
import { ObjectKey } from './ObjectKey'
|
|
|
|
|
|
|
|
|
|
export enum ResourceUsage {
|
|
|
|
|
|
|
|
|
|
PLACEHOLDER = 'placeholder',
|
|
|
|
|
RETRYHODLER = 'retryholder',
|
|
|
|
|
ERRORHOLDER = 'errorholder',
|
|
|
|
|
MAIN = 'main'
|
|
|
|
|
}
|
|
|
|
|
import { TaskParams } from './TaskParams'
|
|
|
|
|
import { Constants } from './constants/Constants'
|
|
|
|
|
|
|
|
|
|
export class ImageKnife {
|
|
|
|
|
static readonly SEPARATOR: string = '/'
|
|
|
|
@ -313,16 +308,16 @@ export class ImageKnife {
|
|
|
|
|
this.generateDataCacheKey(request)
|
|
|
|
|
// 首先执行占位图 解析任务
|
|
|
|
|
if (request.placeholderSrc) {
|
|
|
|
|
this.taskpoolLoadResource(request, ResourceUsage.PLACEHOLDER);
|
|
|
|
|
this.taskpoolLoadResource(request, Constants.PLACE_HOLDER);
|
|
|
|
|
}
|
|
|
|
|
// 其次执行重试占位图 解析任务
|
|
|
|
|
if (request.retryholderSrc) {
|
|
|
|
|
this.taskpoolLoadResource(request, ResourceUsage.RETRYHODLER);
|
|
|
|
|
this.taskpoolLoadResource(request, Constants.RETRY_HOLDER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 最后解析错误占位图
|
|
|
|
|
if (request.errorholderSrc) {
|
|
|
|
|
this.taskpoolLoadResource(request, ResourceUsage.ERRORHOLDER);
|
|
|
|
|
this.taskpoolLoadResource(request, Constants.ERROR_HOLDER);
|
|
|
|
|
}
|
|
|
|
|
return this.parseSource(request);
|
|
|
|
|
}
|
|
|
|
@ -435,7 +430,7 @@ export class ImageKnife {
|
|
|
|
|
this.runningMaps.put(nextPending.uuid, nextPending);
|
|
|
|
|
|
|
|
|
|
// RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
|
|
|
|
this.taskpoolLoadResource(nextPending, ResourceUsage.MAIN);
|
|
|
|
|
this.taskpoolLoadResource(nextPending, Constants.MAIN_HOLDER);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -466,7 +461,7 @@ export class ImageKnife {
|
|
|
|
|
this.runningMaps.put(nextPending.uuid, nextPending)
|
|
|
|
|
this.pendingMaps.remove(nextPending.uuid)
|
|
|
|
|
//RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
|
|
|
|
this.taskpoolLoadResource(nextPending, ResourceUsage.MAIN);
|
|
|
|
|
this.taskpoolLoadResource(nextPending, Constants.MAIN_HOLDER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -518,7 +513,7 @@ export class ImageKnife {
|
|
|
|
|
} else {
|
|
|
|
|
this.runningMaps.put(request.uuid, request)
|
|
|
|
|
|
|
|
|
|
this.taskpoolLoadResource(request, ResourceUsage.MAIN);
|
|
|
|
|
this.taskpoolLoadResource(request, Constants.MAIN_HOLDER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@ -527,66 +522,98 @@ export class ImageKnife {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//多线程请求加载资源
|
|
|
|
|
private taskpoolLoadResource(request: RequestOption, usageType: ResourceUsage) {
|
|
|
|
|
let mainCache = this.memoryCacheProxy.loadMemoryCache(request.generateCacheKey, request.isCacheable);
|
|
|
|
|
let placeholderCache = this.memoryCacheProxy.loadMemoryCache(request.placeholderCacheKey, true);
|
|
|
|
|
let retryholderCache = this.memoryCacheProxy.loadMemoryCache(request.retryholderCacheKey, true);
|
|
|
|
|
let errorholderCacheKey = this.memoryCacheProxy.loadMemoryCache(request.errorholderCacheKey, true);
|
|
|
|
|
//组装任务参数
|
|
|
|
|
private assembleTaskParams(request: RequestOption, usageType: string) {
|
|
|
|
|
//图片变换方法无法直接传递到子线程,这里先把对象名和构造参数传递到子线程,然后在子线程中实例化变换方法
|
|
|
|
|
let transformations: string [][] = [];
|
|
|
|
|
if (usageType == Constants.MAIN_HOLDER) {
|
|
|
|
|
for (let i = 0; i < request.transformations.length; i++) {
|
|
|
|
|
transformations.push([request.transformations[i].getClassName(), request.transformations[i].getConstructorParams()])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let displayProgress = request.progressFunc ? true : false;
|
|
|
|
|
//將要传递到子线程的参数,放在一个json对象上,避免方法参数过多
|
|
|
|
|
let taskParams: TaskParams = {
|
|
|
|
|
headers: request.headers,
|
|
|
|
|
moduleContext: request.moduleContext,
|
|
|
|
|
transformations: transformations,
|
|
|
|
|
usageType: usageType,
|
|
|
|
|
displayProgress: displayProgress,
|
|
|
|
|
uuid: request.uuid,
|
|
|
|
|
dontAnimateFlag: request.dontAnimateFlag,
|
|
|
|
|
generateCacheKey: request.generateCacheKey,
|
|
|
|
|
generateResourceKey: request.generateResourceKey,
|
|
|
|
|
generateDataKey: request.generateDataKey,
|
|
|
|
|
thumbSizeMultiplier: request.thumbSizeMultiplier,
|
|
|
|
|
thumbDelayTime: request.thumbDelayTime,
|
|
|
|
|
size: request.size,
|
|
|
|
|
onlyRetrieveFromCache: request.onlyRetrieveFromCache,
|
|
|
|
|
gpuEnabled: request.gpuEnabled,
|
|
|
|
|
signature: request.signature,
|
|
|
|
|
isCacheable: request.isCacheable
|
|
|
|
|
}
|
|
|
|
|
return taskParams;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (usageType == "placeholder" && placeholderCache && !mainCache && !retryholderCache && !errorholderCacheKey) {
|
|
|
|
|
//多线程请求加载资源
|
|
|
|
|
private taskpoolLoadResource(request: RequestOption, usageType: string) {
|
|
|
|
|
let mainCache = this.memoryCacheProxy.loadMemoryCache(request.generateCacheKey, request.isCacheable);
|
|
|
|
|
let placeholderCache = this.memoryCacheProxy.loadMemoryCache(request.placeholderCacheKey, request.isCacheable);
|
|
|
|
|
let retryholderCache = this.memoryCacheProxy.loadMemoryCache(request.retryholderCacheKey, request.isCacheable);
|
|
|
|
|
let errorholderCacheKey = this.memoryCacheProxy.loadMemoryCache(request.errorholderCacheKey, request.isCacheable);
|
|
|
|
|
|
|
|
|
|
if (usageType == Constants.PLACE_HOLDER && placeholderCache && !mainCache && !retryholderCache && !errorholderCacheKey) {
|
|
|
|
|
LogUtil.info("imageknife load placeholder from MemoryCache")
|
|
|
|
|
request.placeholderOnComplete(placeholderCache);
|
|
|
|
|
return;
|
|
|
|
|
} else if (usageType == "retryholder" && retryholderCache && !mainCache && !errorholderCacheKey) {
|
|
|
|
|
} else if (usageType == Constants.RETRY_HOLDER && retryholderCache && !mainCache && !errorholderCacheKey) {
|
|
|
|
|
LogUtil.info("imageknife load retryholder from MemoryCache")
|
|
|
|
|
request.retryholderOnComplete(retryholderCache);
|
|
|
|
|
return;
|
|
|
|
|
} else if (usageType == "errorholder" && errorholderCacheKey && !mainCache) {
|
|
|
|
|
} else if (usageType == Constants.ERROR_HOLDER && errorholderCacheKey && !mainCache) {
|
|
|
|
|
LogUtil.info("imageknife load errorholder from MemoryCache")
|
|
|
|
|
request.errorholderOnComplete(errorholderCacheKey);
|
|
|
|
|
return;
|
|
|
|
|
} else if (usageType == "main" && mainCache) {
|
|
|
|
|
} else if (usageType == Constants.MAIN_HOLDER && mainCache) {
|
|
|
|
|
LogUtil.info("imageknife load mainsource from MemoryCache")
|
|
|
|
|
mainCache.waitSaveDisk = false;
|
|
|
|
|
request.loadComplete(mainCache);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//图片变换方法无法直接传递到子线程,这里先把对象名和构造参数传递到子线程,然后在子线程中实例化变换方法
|
|
|
|
|
let transformations: string [][] = [];
|
|
|
|
|
if (usageType == ResourceUsage.MAIN) {
|
|
|
|
|
for (let i = 0; i < request.transformations.length; i++) {
|
|
|
|
|
transformations.push([request.transformations[i].getClassName(), request.transformations[i].getConstructorParams()])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//將要传递到子线程的参数,放在一个json对象上,避免方法参数过多
|
|
|
|
|
let taskParams = JSON.stringify({
|
|
|
|
|
transformations: transformations,
|
|
|
|
|
request: request,
|
|
|
|
|
usageType: usageType
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
let taskParams: TaskParams = this.assembleTaskParams(request, usageType);
|
|
|
|
|
let loadSrcJson = JSON.stringify({
|
|
|
|
|
loadSrc: request.loadSrc,
|
|
|
|
|
placeholderSrc: request.placeholderSrc,
|
|
|
|
|
errorholderSrc: request.errorholderSrc,
|
|
|
|
|
retryholderSrc: request.retryholderSrc,
|
|
|
|
|
});
|
|
|
|
|
//使用taskpool多线程执行资源下载
|
|
|
|
|
let task = new taskpool.Task(taskExecute, taskParams, request.headers, request.moduleContext as common.UIAbilityContext)
|
|
|
|
|
let task = new taskpool.Task(taskExecute, taskParams, loadSrcJson)
|
|
|
|
|
task.setTransferList([])
|
|
|
|
|
|
|
|
|
|
emitter.on(Constants.PROGRESS_EMITTER, (data) => {
|
|
|
|
|
if (request.progressFunc && data?.data?.value) {
|
|
|
|
|
let percent = data.data.value as number;
|
|
|
|
|
request.progressFunc.asyncSuccess(percent);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
taskpool.execute(task).then((data) => {
|
|
|
|
|
if (usageType == "placeholder") {
|
|
|
|
|
if (usageType == Constants.PLACE_HOLDER) {
|
|
|
|
|
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
|
|
|
|
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
|
|
|
|
request.placeholderOnComplete(imageKnifeData)
|
|
|
|
|
} else {
|
|
|
|
|
request.placeholderOnError("request placeholder error")
|
|
|
|
|
}
|
|
|
|
|
} else if (usageType == "retryholder") {
|
|
|
|
|
} else if (usageType == Constants.RETRY_HOLDER) {
|
|
|
|
|
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
|
|
|
|
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
|
|
|
|
request.retryholderOnComplete(imageKnifeData)
|
|
|
|
|
} else {
|
|
|
|
|
request.retryholderOnError("request retryholder error")
|
|
|
|
|
}
|
|
|
|
|
} else if (usageType == "errorholder") {
|
|
|
|
|
} else if (usageType == Constants.ERROR_HOLDER) {
|
|
|
|
|
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
|
|
|
|
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
|
|
|
|
request.errorholderOnComplete(imageKnifeData)
|
|
|
|
@ -684,51 +711,65 @@ export class ImageKnife {
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
@Concurrent
|
|
|
|
|
async function taskExecute(taskParams: string, headers: Map<string, Object>, moduleContext: common.UIAbilityContext): Promise<PixelMap | GIFFrame[]> {
|
|
|
|
|
async function taskExecute(taskParams: TaskParams, loadSrcJson: string): Promise<PixelMap | GIFFrame[]> {
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
let params: object = JSON.parse(taskParams);
|
|
|
|
|
let option = params["request"] as RequestOption;
|
|
|
|
|
let transformations = params["transformations"] as string [][];
|
|
|
|
|
let usageType = params["usageType"] as string;
|
|
|
|
|
let emitProgressPercent = (percentValue: number) => {
|
|
|
|
|
let eventData: emitter.EventData = {
|
|
|
|
|
data: {
|
|
|
|
|
"value": percentValue,
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
emitter.emit(Constants.PROGRESS_EMITTER, eventData)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let transformations = taskParams.transformations;
|
|
|
|
|
let usageType = taskParams.usageType;
|
|
|
|
|
let displayProgress = taskParams.displayProgress;
|
|
|
|
|
//子线程构造RequestOption对象
|
|
|
|
|
let newRequestOption = new RequestOption();
|
|
|
|
|
newRequestOption.uuid = option.uuid;
|
|
|
|
|
newRequestOption.loadSrc = option.loadSrc;
|
|
|
|
|
newRequestOption.dontAnimateFlag = option.dontAnimateFlag;
|
|
|
|
|
newRequestOption.generateCacheKey = option.generateCacheKey;
|
|
|
|
|
newRequestOption.generateResourceKey = option.generateResourceKey;
|
|
|
|
|
newRequestOption.generateDataKey = option.generateDataKey;
|
|
|
|
|
newRequestOption.thumbSizeMultiplier = option.thumbSizeMultiplier;
|
|
|
|
|
newRequestOption.thumbDelayTime = option.thumbDelayTime;
|
|
|
|
|
newRequestOption.size = option.size;
|
|
|
|
|
let loadSrcObj: object = JSON.parse(loadSrcJson);
|
|
|
|
|
newRequestOption.uuid = taskParams.uuid;
|
|
|
|
|
newRequestOption.loadSrc = loadSrcObj["loadSrc"] as string | PixelMap | Resource;
|
|
|
|
|
newRequestOption.dontAnimateFlag = taskParams.dontAnimateFlag;
|
|
|
|
|
newRequestOption.generateCacheKey = taskParams.generateCacheKey;
|
|
|
|
|
newRequestOption.generateResourceKey = taskParams.generateResourceKey;
|
|
|
|
|
newRequestOption.generateDataKey = taskParams.generateDataKey;
|
|
|
|
|
newRequestOption.thumbSizeMultiplier = taskParams.thumbSizeMultiplier;
|
|
|
|
|
newRequestOption.thumbDelayTime = taskParams.thumbDelayTime;
|
|
|
|
|
newRequestOption.size = taskParams.size;
|
|
|
|
|
|
|
|
|
|
newRequestOption.placeholderSrc = option.placeholderSrc;
|
|
|
|
|
newRequestOption.errorholderSrc = option.errorholderSrc;
|
|
|
|
|
newRequestOption.retryholderSrc = option.retryholderSrc;
|
|
|
|
|
newRequestOption.onlyRetrieveFromCache = option.onlyRetrieveFromCache;
|
|
|
|
|
newRequestOption.gpuEnabled = option.gpuEnabled;
|
|
|
|
|
newRequestOption.headers = headers;
|
|
|
|
|
newRequestOption.signature = option.signature;
|
|
|
|
|
ImageKnifeGlobal.getInstance().setHapContext(moduleContext);
|
|
|
|
|
newRequestOption.moduleContext = moduleContext;
|
|
|
|
|
if (option.isCacheable != null && option.isCacheable != undefined) {
|
|
|
|
|
newRequestOption.isCacheable = option.isCacheable;
|
|
|
|
|
newRequestOption.placeholderSrc = loadSrcObj["placeholderSrc"] as PixelMap | Resource | undefined;
|
|
|
|
|
newRequestOption.errorholderSrc = loadSrcObj["errorholderSrc"] as PixelMap | Resource | undefined;
|
|
|
|
|
newRequestOption.retryholderSrc = loadSrcObj["retryholderSrc"] as PixelMap | Resource | undefined;
|
|
|
|
|
newRequestOption.onlyRetrieveFromCache = taskParams.onlyRetrieveFromCache;
|
|
|
|
|
newRequestOption.gpuEnabled = taskParams.gpuEnabled;
|
|
|
|
|
newRequestOption.headers = taskParams.headers;
|
|
|
|
|
newRequestOption.signature = taskParams.signature;
|
|
|
|
|
ImageKnifeGlobal.getInstance().setHapContext(taskParams.moduleContext as common.UIAbilityContext);
|
|
|
|
|
newRequestOption.moduleContext = taskParams.moduleContext;
|
|
|
|
|
newRequestOption.isCacheable = taskParams.isCacheable;
|
|
|
|
|
|
|
|
|
|
if (displayProgress) {
|
|
|
|
|
newRequestOption.addProgressListener({
|
|
|
|
|
asyncSuccess: (percentValue: number) => {
|
|
|
|
|
// 如果进度条百分比 未展示大小,展示其动画
|
|
|
|
|
emitProgressPercent(percentValue)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
//如果是本地图片不作磁盘缓存
|
|
|
|
|
if (typeof option.loadSrc !== 'string') {
|
|
|
|
|
if (typeof newRequestOption.loadSrc !== 'string') {
|
|
|
|
|
let none = new NONE();
|
|
|
|
|
newRequestOption.diskCacheStrategy(none);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (usageType == "placeholder") {
|
|
|
|
|
if (usageType == Constants.PLACE_HOLDER) {
|
|
|
|
|
let manager = new PlaceHolderManager<PixelMap>(newRequestOption);
|
|
|
|
|
return await new Promise<PixelMap>(manager.process);
|
|
|
|
|
} else if (usageType == "retryholder") {
|
|
|
|
|
} else if (usageType == Constants.RETRY_HOLDER) {
|
|
|
|
|
let manager = new RetryHolderManager<PixelMap>(newRequestOption);
|
|
|
|
|
return await new Promise<PixelMap>(manager.process);
|
|
|
|
|
} else if (usageType == "errorholder") {
|
|
|
|
|
} else if (usageType == Constants.ERROR_HOLDER) {
|
|
|
|
|
let manager = new ErrorHolderManager<PixelMap>(newRequestOption);
|
|
|
|
|
return await new Promise<PixelMap>(manager.process);
|
|
|
|
|
} else {
|
|
|
|
@ -744,9 +785,5 @@ async function taskExecute(taskParams: string, headers: Map<string, Object>, mod
|
|
|
|
|
let manager = new RequestManager(newRequestOption, newDataFetch, newResourceFetch);
|
|
|
|
|
return await new Promise<PixelMap | GIFFrame[]>(manager.process);
|
|
|
|
|
}
|
|
|
|
|
// } catch (e) {
|
|
|
|
|
// console.log(e)
|
|
|
|
|
// return await new Promise<PixelMap | GIFFrame[]>(() => {
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|