Compare commits

..

2 Commits

Author SHA1 Message Date
zgf ddab4f22a6
Pre Merge pull request !459 from zgf/master 2025-02-13 04:14:24 +00:00
zgf 23a9ac54b2 增加ImageKnifeComponent组件销毁网络请求中断
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2025-02-13 12:14:12 +08:00
5 changed files with 84 additions and 79 deletions

View File

@ -177,10 +177,10 @@ export class ImageKnife {
* @param request 图片请求request
*/
cancel(request:ImageKnifeRequest) {
request.requestState = ImageKnifeRequestState.DESTROY
if (typeof request.imageKnifeOption.loadSrc === 'string') {
if (typeof request?.imageKnifeOption.loadSrc === 'string' && !request?.drawMainSuccess) {
emitter.emit(request.imageKnifeOption.loadSrc + request.componentId)
}
request.requestState = ImageKnifeRequestState.DESTROY
}
/**
* 预加载图片到文件缓存

View File

@ -87,6 +87,7 @@ export class ImageKnifeDispatcher {
if (requestSource == ImageKnifeRequestSource.SRC) {
request.requestState = ImageKnifeRequestState.COMPLETE
request.drawMainSuccess = true
// 回调请求开结束
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData);
@ -177,7 +178,9 @@ export class ImageKnifeDispatcher {
if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) {
this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)
}
if (request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
request.imageKnifeOption.onLoadListener?.onLoadStart(request)
}
// 加载主图
this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)
LogUtil.log('executeJob.end:' + request.componentId + ',version:' + request.componentVersion)
@ -188,9 +191,6 @@ export class ImageKnifeDispatcher {
*/
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)
}
let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator, currentRequest.componentWidth, currentRequest.componentHeight)
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
@ -353,29 +353,27 @@ export class ImageKnifeDispatcher {
}
let pixelmap = requestJobResult.pixelMap;
if (pixelmap === undefined) {
// 请求取消
if (currentRequest.requestState === ImageKnifeRequestState.DESTROY) {
this.executingJobMap.remove(memoryKey);
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
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);
}
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
if (currentRequest.componentId !== requestWithSource.request.componentId && requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
// 加载占位符
if (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
requestWithSource.request.imageKnifeOption.placeholderSrc !== undefined &&
requestWithSource.request.drawPlayHolderSuccess == false) {
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)
} else if (requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER &&
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.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc, ImageKnifeRequestSource.ERROR_HOLDER)
} else if (requestWithSource.source === ImageKnifeRequestSource.SRC) {
// 加载主图
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC)
}
} else {
if (pixelmap !== undefined && typeof pixelmap !== 'string') {
(pixelmap as PixelMap).release()
}
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
// 回调请求成功
// 回调请求成功
@ -394,6 +392,35 @@ export class ImageKnifeDispatcher {
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel(requestJobResult.loadFail ?? 'component has destroyed from load', requestWithSource.request)
}
}
})
this.dispatchNextJob()
return
}
// 请求失败
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);
}
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;
@ -432,15 +459,15 @@ export class ImageKnifeDispatcher {
//构建缓存保存的ImageKnifeData
let saveCacheImageData: ImageKnifeData = {
source: pixelmap!,
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
imageWidth: requestJobResult.size?.width ?? 0,
imageHeight: requestJobResult.size?.height ?? 0,
type: requestJobResult.type,
bufSize: requestJobResult.bufferSize,
imageAnimator: imageKnifeData.imageAnimator
}
// 保存内存缓存
if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File && currentRequest.requestState !== ImageKnifeRequestState.DESTROY) {
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),
@ -450,53 +477,31 @@ export class ImageKnifeDispatcher {
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)) {
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight },
requestWithSource.source, imageKnifeData.imageAnimator);
}
// 画主图
if (requestWithSource.source === ImageKnifeRequestSource.SRC ||
requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight },
requestWithSource.source, imageKnifeData.imageAnimator);
}
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);
}
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
}
} else {
if (typeof currentRequest.imageKnifeData?.source !== 'string') {
(currentRequest.imageKnifeData?.source as PixelMap).release()
}
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE;
requestWithSource.request.drawMainSuccess = true
if (requestWithSource.request.imageKnifeOption.onLoadListener &&
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
// 回调请求成功
// 回调请求成功
//设置失败回调的时间点
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 from load', requestWithSource.request)
this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, imageKnifeData,
requestWithSource.request);
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source,
saveCacheImageData, requestWithSource.request);
}
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
}
});
this.executingJobMap.remove(memoryKey);
this.dispatchNextJob();
} else {

View File

@ -30,7 +30,7 @@ export struct ImageKnifeComponent {
@State adaptiveWidth: Length = '100%'
@State adaptiveHeight: Length | undefined = '100%'
@State objectFit: ImageFit = ImageFit.Contain
private componentId: number = this.getUniqueId()
private componentId: number = 0
private request: ImageKnifeRequest | undefined
private lastWidth: number = 0
private lastHeight: number = 0
@ -42,7 +42,7 @@ export struct ImageKnifeComponent {
aboutToAppear(): void {
this.objectFit = (this.imageKnifeOption.objectFit === undefined || this.imageKnifeOption.objectFit === ImageFit.Auto) ? ImageFit.Contain : this.imageKnifeOption.objectFit
this.componentId = this.getUniqueId()
if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题建议使用同步方式在aboutToAppear时加载图片
let engineKey: IEngineKey = new DefaultEngineKey();
let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
@ -78,8 +78,8 @@ export struct ImageKnifeComponent {
}
emitterDestroy() {
if (typeof this.imageKnifeOption.loadSrc === 'string') {
emitter.emit(this.imageKnifeOption.loadSrc + this.componentId)
if (typeof this.request?.imageKnifeOption.loadSrc === 'string' && !this.request?.drawMainSuccess) {
emitter.emit(this.request.imageKnifeOption.loadSrc + this.componentId)
}
}
/**

View File

@ -61,8 +61,7 @@ export class HttpLoaderStrategy implements IImageLoaderStrategy {
${request.componentVersion}`);
callBackTimeInfo.netRequestStartTime = Date.now();
const httpRequest = http.createHttp();
emitter.on((request.src as string) + request.componentId,()=>{
emitter.off((request.src as string) + request.componentId)
emitter.once((request.src as string) + request.componentId,()=>{
httpRequest.destroy()
})
let progress: number = 0;
@ -99,13 +98,12 @@ export class HttpLoaderStrategy implements IImageLoaderStrategy {
header: headerObj,
method: http.RequestMethod.GET,
expectDataType: http.HttpDataType.ARRAY_BUFFER,
connectTimeout: request.connectTimeout === undefined || request.connectTimeout === null ?
60000 : request.connectTimeout,
readTimeout: request.readTimeout === undefined || request.readTimeout === null?
30000 : request.readTimeout,
connectTimeout: request.connectTimeout ?? 60000,
readTimeout: request.readTimeout ?? 30000,
caPath: request.caPath
});
promise.then((data: number) => {
emitter.off((request.src as string) + request.componentId)
callBackData.httpCode = data;
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, undefined);
callBackTimeInfo.netRequestEndTime = Date.now();
@ -118,6 +116,7 @@ export class HttpLoaderStrategy implements IImageLoaderStrategy {
LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE));
}
}).catch((err: BusinessError) => {
emitter.off((request.src as string) + request.componentId)
callBackData.httpCode = err.code;
loadError = 'HttpDownloadClient download ERROR : err = ' + JSON.stringify(err);
callBackTimeInfo.netRequestEndTime = Date.now();

View File

@ -22,6 +22,7 @@ export class ImageKnifeRequest {
componentWidth: number = 0
componentHeight: number = 0
drawPlayHolderSuccess: boolean = false
drawMainSuccess: boolean = false
imageKnifeOption: ImageKnifeOption
context: common.UIAbilityContext
ImageKnifeRequestCallback: ImageKnifeRequestCallback