增加ImageKnifeComponent组件销毁网络请求中断

Signed-off-by: zgf <zenggaofeng2@h-partners.com>
This commit is contained in:
zgf 2025-02-10 17:19:49 +08:00
parent 933cc284ec
commit 8601f87865
8 changed files with 194 additions and 115 deletions

View File

@ -1,3 +1,7 @@
## 3.2.2-rc.0
- Add ImageKnifeComponent to destroy network request interruption
- Code refactoring during the download of image resources stage
## 3.2.1 ## 3.2.1
- Release official version - Release official version

View File

@ -108,7 +108,7 @@ struct MultipleImageCallBack {
console.log('image load multiple loadFail:' + this.failIndex) console.log('image load multiple loadFail:' + this.failIndex)
}, },
onLoadCancel:(message,request)=>{ onLoadCancel:(message,request)=>{
let flag = request?.imageKnifeData?.type ? true : false let flag = request?.imageKnifeData?.timeInfo?.netRequestStartTime ? true : false
if (flag) { if (flag) {
this.cancelLoadIndex++ this.cancelLoadIndex++
} else { } else {

View File

@ -25,6 +25,7 @@ import { util } from '@kit.ArkTS';
import { image } from '@kit.ImageKit'; import { image } from '@kit.ImageKit';
import { common } from '@kit.AbilityKit'; import { common } from '@kit.AbilityKit';
import { LogUtil } from './utils/LogUtil'; import { LogUtil } from './utils/LogUtil';
import { emitter } from '@kit.BasicServicesKit';
export class ImageKnife { export class ImageKnife {
@ -176,6 +177,9 @@ export class ImageKnife {
* @param request 图片请求request * @param request 图片请求request
*/ */
cancel(request:ImageKnifeRequest) { cancel(request:ImageKnifeRequest) {
if (typeof request?.imageKnifeOption.loadSrc === 'string' && !request?.drawMainSuccess) {
emitter.emit(request.imageKnifeOption.loadSrc + request.componentId)
}
request.requestState = ImageKnifeRequestState.DESTROY request.requestState = ImageKnifeRequestState.DESTROY
} }
/** /**
@ -462,12 +466,12 @@ export class ImageKnife {
return false return false
} }
async execute(request: ImageKnifeRequest,isAnimator?: boolean): Promise<void> { async execute(request: ImageKnifeRequest): Promise<void> {
LogUtil.log('ImageKnife_DataTime_execute.start:'+request.imageKnifeOption.loadSrc) LogUtil.log('ImageKnife_DataTime_execute.start:'+request.imageKnifeOption.loadSrc)
if (this.headerMap.size > 0) { if (this.headerMap.size > 0) {
request.addHeaderMap(this.headerMap) request.addHeaderMap(this.headerMap)
} }
this.dispatcher.enqueue(request,isAnimator) this.dispatcher.enqueue(request)
LogUtil.log('ImageKnife_DataTime_execute.end:'+request.imageKnifeOption.loadSrc) LogUtil.log('ImageKnife_DataTime_execute.end:'+request.imageKnifeOption.loadSrc)
} }

View File

@ -87,6 +87,7 @@ export class ImageKnifeDispatcher {
if (requestSource == ImageKnifeRequestSource.SRC) { if (requestSource == ImageKnifeRequestSource.SRC) {
request.requestState = ImageKnifeRequestState.COMPLETE request.requestState = ImageKnifeRequestState.COMPLETE
request.drawMainSuccess = true
// 回调请求开结束 // 回调请求开结束
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) { if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData); this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData);
@ -150,11 +151,11 @@ export class ImageKnifeDispatcher {
request.imageKnifeData = callBackData; request.imageKnifeData = callBackData;
} }
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void { enqueue(request: ImageKnifeRequest,): void {
//初始化加载回调信息 //初始化加载回调信息
this.initCallData(request); this.initCallData(request);
//1.内存有的话直接渲染 //1.内存有的话直接渲染
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) { if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,request.animator)) {
return return
} }
// 2.内存获取占位图 // 2.内存获取占位图
@ -168,18 +169,20 @@ export class ImageKnifeDispatcher {
this.jobQueue.add(request) this.jobQueue.add(request)
return return
} }
this.executeJob(request,isAnimator) this.executeJob(request)
} }
executeJob(request: ImageKnifeRequest,isAnimator?: boolean): void { executeJob(request: ImageKnifeRequest): void {
LogUtil.log('executeJob.start:' + request.componentId + ',version:' + request.componentVersion) LogUtil.log('executeJob.start:' + request.componentId + ',version:' + request.componentVersion)
// 加载占位符 // 加载占位符
if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) { if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) {
this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) 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) this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,request.animator)
LogUtil.log('executeJob.end:' + request.componentId + ',version:' + request.componentVersion) 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 { getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void {
LogUtil.log('getAndShowImage.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion) 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 memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator, currentRequest.componentWidth, currentRequest.componentHeight)
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey) let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
@ -353,17 +353,64 @@ export class ImageKnifeDispatcher {
} }
let pixelmap = requestJobResult.pixelMap; let pixelmap = requestJobResult.pixelMap;
// 请求取消
if (currentRequest.requestState === ImageKnifeRequestState.DESTROY) {
this.executingJobMap.remove(memoryKey);
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
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) {
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,requestWithSource.request.animator)
}
} else {
if (pixelmap !== undefined && typeof pixelmap !== 'string') {
(pixelmap as PixelMap).release()
}
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(requestJobResult.loadFail ?? 'component has destroyed from load', requestWithSource.request)
}
}
})
this.dispatchNextJob()
return
}
// 请求失败
if (pixelmap === undefined) { if (pixelmap === undefined) {
this.executingJobMap.remove(memoryKey); this.executingJobMap.remove(memoryKey);
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR requestWithSource.request.requestState = ImageKnifeRequestState.ERROR
LogUtil.error('getAndShowImage_CallBack.pixelmap failed:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion + " error: " + requestJobResult.loadFail) LogUtil.error('getAndShowImage_CallBack.pixelmap failed:' + currentRequest.componentId + ',srcType:' +
requestSource + ',version:' + currentRequest.componentVersion + " error: " + requestJobResult.loadFail)
// 回调请求失败 // 回调请求失败
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.imageKnifeData, requestJobResult.imageKnifeData, requestWithSource.request) this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, requestJobResult.imageKnifeData,
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request); requestWithSource.request)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,
requestWithSource.request);
} }
if (requestWithSource.source === ImageKnifeRequestSource.SRC && if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) { requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
@ -412,8 +459,8 @@ export class ImageKnifeDispatcher {
//构建缓存保存的ImageKnifeData //构建缓存保存的ImageKnifeData
let saveCacheImageData: ImageKnifeData = { let saveCacheImageData: ImageKnifeData = {
source: pixelmap!, source: pixelmap!,
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width, imageWidth: requestJobResult.size?.width ?? 0,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height, imageHeight: requestJobResult.size?.height ?? 0,
type: requestJobResult.type, type: requestJobResult.type,
bufSize: requestJobResult.bufferSize, bufSize: requestJobResult.bufferSize,
imageAnimator: imageKnifeData.imageAnimator imageAnimator: imageKnifeData.imageAnimator
@ -430,50 +477,31 @@ export class ImageKnifeDispatcher {
if (requestList !== undefined) { if (requestList !== undefined) {
// key相同的request一起绘制 // key相同的request一起绘制
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) { // 画主图
// 画主图 if (requestWithSource.source === ImageKnifeRequestSource.SRC ||
if (requestWithSource.source === ImageKnifeRequestSource.SRC || requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER || (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER && requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) { requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight },
imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight }, requestWithSource.source, imageKnifeData.imageAnimator);
requestWithSource.source, imageKnifeData.imageAnimator); }
}
if (requestWithSource.source == ImageKnifeRequestSource.SRC) { if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE; requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE;
if (requestWithSource.request.imageKnifeOption.onLoadListener && requestWithSource.request.drawMainSuccess = true
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) { 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 (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
// 回调请求成功 // 回调请求成功
// 回调请求成功 this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, imageKnifeData,
//设置失败回调的时间点 requestWithSource.request);
let callBackData = requestWithSource.request.imageKnifeData; requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source,
saveCacheImageData, requestWithSource.request);
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)
} }
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
} }
}); });
this.executingJobMap.remove(memoryKey); this.executingJobMap.remove(memoryKey);
this.dispatchNextJob(); this.dispatchNextJob();
} else { } else {

View File

@ -18,6 +18,7 @@ import common from '@ohos.app.ability.common';
import { ImageKnife } from '../ImageKnife'; import { ImageKnife } from '../ImageKnife';
import { LogUtil } from '../utils/LogUtil'; import { LogUtil } from '../utils/LogUtil';
import { ImageKnifeRequestSource } from '../model/ImageKnifeData'; import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
import { emitter } from '@kit.BasicServicesKit';
@Component @Component
export struct ImageKnifeAnimatorComponent { export struct ImageKnifeAnimatorComponent {
@ -26,11 +27,13 @@ export struct ImageKnifeAnimatorComponent {
@State pixelMap: PixelMap | string | undefined = undefined @State pixelMap: PixelMap | string | undefined = undefined
@State imageAnimator: Array<ImageFrameInfo> | undefined = undefined @State imageAnimator: Array<ImageFrameInfo> | undefined = undefined
@State adaptiveWidth: Length = '100%' @State adaptiveWidth: Length = '100%'
@State adaptiveHeight: Length = '100%' @State adaptiveHeight: Length | undefined = '100%'
@State objectFit: ImageFit = ImageFit.Contain @State objectFit: ImageFit = ImageFit.Contain
private componentId: number = 0
private request: ImageKnifeRequest | undefined private request: ImageKnifeRequest | undefined
private lastWidth: number = 0 private lastWidth: number = 0
private lastHeight: number = 0 private lastHeight: number = 0
private isImageFitAutoResize: boolean = false
private currentWidth: number = 0 private currentWidth: number = 0
private currentHeight: number = 0 private currentHeight: number = 0
private componentVersion: number = 0 private componentVersion: number = 0
@ -38,23 +41,33 @@ export struct ImageKnifeAnimatorComponent {
aboutToAppear(): void { aboutToAppear(): void {
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
this.componentId = this.getUniqueId()
} }
aboutToDisappear(): void { aboutToDisappear(): void {
if (this.request !== undefined) { this.emitterDestroy()
this.request.requestState = ImageKnifeRequestState.DESTROY this.clearLastRequest()
this.request = undefined
}
} }
aboutToRecycle() { aboutToRecycle() {
this.emitterDestroy()
this.clearLastRequest()
}
emitterDestroy() {
if (typeof this.request?.imageKnifeOption.loadSrc === 'string' && !this.request?.drawMainSuccess) {
emitter.emit(this.request.imageKnifeOption.loadSrc + this.componentId)
}
}
/**
* 对已DESTROY的组件不再发起请求
*/
private clearLastRequest(){
if (this.request !== undefined) { if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY this.request.requestState = ImageKnifeRequestState.DESTROY
this.request = undefined this.request = undefined
} }
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} }
build() { build() {
ImageAnimator() ImageAnimator()
.images(this.imageAnimator) .images(this.imageAnimator)
@ -79,8 +92,14 @@ export struct ImageKnifeAnimatorComponent {
' loadSrc = ' + this.imageKnifeOption.loadSrc + ' loadSrc = ' + this.imageKnifeOption.loadSrc +
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc + ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc + ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
' componentId = ' + this.getUniqueId()) ' componentId = ' + this.componentId)
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true)
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize) {
this.isImageFitAutoResize = false
} else {
ImageKnife.getInstance().execute(this.getRequest(
this.currentWidth, this.currentHeight, this.componentId))
}
} }
} }
}) })
@ -92,17 +111,17 @@ export struct ImageKnifeAnimatorComponent {
} }
watchImageKnifeOption() { watchImageKnifeOption() {
if (this.request !== undefined) { this.clearLastRequest()
this.request.requestState = ImageKnifeRequestState.DESTROY
}
this.request = undefined
this.componentVersion++ this.componentVersion++
this.isImageFitAutoResize = false
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight + LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
' loadSrc = ' + this.imageKnifeOption.loadSrc + ' loadSrc = ' + this.imageKnifeOption.loadSrc +
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc + ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc + ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
' componentId = ' + this.getUniqueId()) ' componentId = ' + this.componentId)
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true) ImageKnife.getInstance().execute(this.getRequest(
this.currentWidth, this.currentHeight, this.componentId))
} }
getCurrentContext(): common.UIAbilityContext { getCurrentContext(): common.UIAbilityContext {
@ -112,43 +131,52 @@ export struct ImageKnifeAnimatorComponent {
return this.currentContext return this.currentContext
} }
getRequest(width: number, height: number): ImageKnifeRequest { getRequest(width: number, height: number,componentId: number): ImageKnifeRequest {
if (this.request == undefined) { this.request = new ImageKnifeRequest(
this.request = new ImageKnifeRequest( this.imageKnifeOption,
this.imageKnifeOption, this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(), width,
width, height,
height, this.componentVersion,
this.componentVersion, {
{ showPixelMap: (version: number, pixelMap: PixelMap | string, size: Size, requestSource: ImageKnifeRequestSource,
showPixelMap: (version: number, pixelMap: PixelMap | string,size: Size, requestSource: ImageKnifeRequestSource,imageAnimator?: Array<ImageFrameInfo>) => { imageAnimator?: Array<ImageFrameInfo>) => {
if (version !== this.componentVersion) { if (version !== this.componentVersion) {
return //针对reuse场景不显示历史图片 return //针对reuse场景不显示历史图片
} }
if (imageAnimator != undefined) { if (imageAnimator != undefined) {
this.imageAnimator = imageAnimator this.imageAnimator = imageAnimator
} else { } else {
this.imageAnimator = [ this.imageAnimator = [
{ {
src: pixelMap src: pixelMap
} }
] ]
}
if (requestSource == ImageKnifeRequestSource.SRC) {
this.objectFit =
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
this.objectFit =
this.imageKnifeOption.placeholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.placeholderObjectFit
} else {
this.objectFit =
this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit
}
} }
})
}
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize == false &&
requestSource == ImageKnifeRequestSource.SRC) {
this.adaptiveHeight = undefined
this.isImageFitAutoResize = true
}
if (requestSource == ImageKnifeRequestSource.SRC) {
this.objectFit =
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
this.objectFit =
this.imageKnifeOption.placeholderObjectFit === undefined ?
(this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) :
this.imageKnifeOption.placeholderObjectFit
} else {
this.objectFit =
this.imageKnifeOption.errorholderObjectFit === undefined ?
(this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) :
this.imageKnifeOption.errorholderObjectFit
}
}
})
this.request.animator = true
return this.request return this.request
} }
} }

View File

@ -20,6 +20,7 @@ import { LogUtil } from '../utils/LogUtil';
import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData'; import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData';
import { IEngineKey } from '../key/IEngineKey'; import { IEngineKey } from '../key/IEngineKey';
import { DefaultEngineKey } from '../key/DefaultEngineKey'; import { DefaultEngineKey } from '../key/DefaultEngineKey';
import { emitter } from '@kit.BasicServicesKit';
@Component @Component
export struct ImageKnifeComponent { export struct ImageKnifeComponent {
@ -29,6 +30,7 @@ export struct ImageKnifeComponent {
@State adaptiveWidth: Length = '100%' @State adaptiveWidth: Length = '100%'
@State adaptiveHeight: Length | undefined = '100%' @State adaptiveHeight: Length | undefined = '100%'
@State objectFit: ImageFit = ImageFit.Contain @State objectFit: ImageFit = ImageFit.Contain
private componentId: number = 0
private request: ImageKnifeRequest | undefined private request: ImageKnifeRequest | undefined
private lastWidth: number = 0 private lastWidth: number = 0
private lastHeight: number = 0 private lastHeight: number = 0
@ -40,7 +42,7 @@ export struct ImageKnifeComponent {
aboutToAppear(): void { aboutToAppear(): void {
this.objectFit = (this.imageKnifeOption.objectFit === undefined || this.imageKnifeOption.objectFit === ImageFit.Auto) ? ImageFit.Contain : this.imageKnifeOption.objectFit this.objectFit = (this.imageKnifeOption.objectFit === undefined || this.imageKnifeOption.objectFit === ImageFit.Auto) ? ImageFit.Contain : this.imageKnifeOption.objectFit
this.componentId = this.getUniqueId()
if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题建议使用同步方式在aboutToAppear时加载图片 if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题建议使用同步方式在aboutToAppear时加载图片
let engineKey: IEngineKey = new DefaultEngineKey(); let engineKey: IEngineKey = new DefaultEngineKey();
let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance() let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
@ -65,13 +67,21 @@ export struct ImageKnifeComponent {
} }
aboutToDisappear(): void { aboutToDisappear(): void {
this.emitterDestroy()
this.clearLastRequest() this.clearLastRequest()
} }
aboutToRecycle() { aboutToRecycle() {
this.pixelMap = ImageContent.EMPTY this.pixelMap = ImageContent.EMPTY
this.emitterDestroy()
this.clearLastRequest() this.clearLastRequest()
} }
emitterDestroy() {
if (typeof this.request?.imageKnifeOption.loadSrc === 'string' && !this.request?.drawMainSuccess) {
emitter.emit(this.request.imageKnifeOption.loadSrc + this.componentId)
}
}
/** /**
* 对已DESTROY的组件不再发起请求 * 对已DESTROY的组件不再发起请求
*/ */
@ -105,13 +115,13 @@ export struct ImageKnifeComponent {
' loadSrc = ' + this.imageKnifeOption.loadSrc + ' loadSrc = ' + this.imageKnifeOption.loadSrc +
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc + ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc + ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
' componentId = ' + this.getUniqueId()) ' componentId = ' + this.componentId)
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize) { if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize) {
this.isImageFitAutoResize = false this.isImageFitAutoResize = false
} else { } else {
ImageKnife.getInstance().execute(this.getRequest( ImageKnife.getInstance().execute(this.getRequest(
this.currentWidth, this.currentHeight, this.getUniqueId())) this.currentWidth, this.currentHeight, this.componentId))
} }
} }
} }
@ -127,9 +137,9 @@ export struct ImageKnifeComponent {
' loadSrc = ' + this.imageKnifeOption.loadSrc + ' loadSrc = ' + this.imageKnifeOption.loadSrc +
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc + ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc + ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
' componentId = ' + this.getUniqueId()) ' componentId = ' + this.componentId)
ImageKnife.getInstance().execute(this.getRequest( ImageKnife.getInstance().execute(this.getRequest(
this.currentWidth, this.currentHeight, this.getUniqueId())) this.currentWidth, this.currentHeight, this.componentId))
} }
getCurrentContext(): common.UIAbilityContext { getCurrentContext(): common.UIAbilityContext {

View File

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

View File

@ -22,6 +22,7 @@ export class ImageKnifeRequest {
componentWidth: number = 0 componentWidth: number = 0
componentHeight: number = 0 componentHeight: number = 0
drawPlayHolderSuccess: boolean = false drawPlayHolderSuccess: boolean = false
drawMainSuccess: boolean = false
imageKnifeOption: ImageKnifeOption imageKnifeOption: ImageKnifeOption
context: common.UIAbilityContext context: common.UIAbilityContext
ImageKnifeRequestCallback: ImageKnifeRequestCallback ImageKnifeRequestCallback: ImageKnifeRequestCallback
@ -29,6 +30,7 @@ export class ImageKnifeRequest {
headers: Map<string,Object> = new Map<string,Object>() headers: Map<string,Object> = new Map<string,Object>()
imageKnifeData?: ImageKnifeData imageKnifeData?: ImageKnifeData
componentId?: number componentId?: number
animator?: boolean
constructor(option: ImageKnifeOption, constructor(option: ImageKnifeOption,
uIAbilityContext: common.UIAbilityContext, uIAbilityContext: common.UIAbilityContext,
width: number, width: number,