diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 72c436c..00222dc 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -36,6 +36,11 @@ struct Index { uri: 'pages/TestCommonImage', }); }) + Button("测试占位图Task报错").margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/TestTaskResourcePage', + }); + }) Button("测试HSP场景预加载").margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/TestHspPreLoadImage', diff --git a/entry/src/main/ets/pages/TestTaskResourcePage.ets b/entry/src/main/ets/pages/TestTaskResourcePage.ets new file mode 100644 index 0000000..0578bca --- /dev/null +++ b/entry/src/main/ets/pages/TestTaskResourcePage.ets @@ -0,0 +1,79 @@ +/* + * 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 { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife" + +@ComponentV2 +export struct ZuImage { + @Param @Require src: PixelMap | ResourceStr | string | undefined + @Param @Require placeholderSrc: PixelMap | ResourceStr | string | undefined + @Local errorholderSrc: PixelMap | ResourceStr | string | undefined + + build() { + if (this.src) { + //当前版本存在bug + ImageKnifeComponent({ + imageKnifeOption: new ImageKnifeOption({ + loadSrc: this.src, + placeholderSrc: this.placeholderSrc, + errorholderSrc: this.errorholderSrc ?? this.placeholderSrc, + objectFit: ImageFit.Cover + }) + }) + } else { + Image(this.placeholderSrc) + .objectFit(ImageFit.Cover) + } + } +} + + +@Entry +@ComponentV2 +struct TestTaskResourcePage { + @Local stateMenus: Array = [ + "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", + 'https://img-blog.csdnimg.cn/20191215043500229.png', + 'https://img-blog.csdn.net/20140514114029140', + 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', + ] + @Builder + _buildItem(item: string) { + Column({ space: 8 }) { + ZuImage({ + src: item, + placeholderSrc: $r("app.media.loading") + }).width(44) + .height(44) + } + } + build() { + + Grid() { + ForEach(this.stateMenus, (item: string) => { + GridItem() { + this._buildItem(item) + } + }) + }.width("100%") + .columnsTemplate('1fr 1fr 1fr 1fr 1fr') + .rowsGap(24) + .padding({ + top: 24, + bottom: 24, + left: 24, + right: 24 + }) + } +} \ No newline at end of file diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index b338822..61bc5cf 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -69,6 +69,7 @@ export class ImageKnifeDispatcher { if (memoryCache !== undefined) { + LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_true:" + request.imageKnifeOption.loadSrc) // 画主图 if (request.requestState === ImageKnifeRequestState.PROGRESS) { // 回调请求开始 @@ -91,7 +92,6 @@ export class ImageKnifeDispatcher { request.requestState = ImageKnifeRequestState.ERROR } } - LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_true:" + request.imageKnifeOption.loadSrc) return true } LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_false:" + request.imageKnifeOption.loadSrc) diff --git a/library/src/main/ets/components/ImageKnifeComponent.ets b/library/src/main/ets/components/ImageKnifeComponent.ets index 29a2b20..1232ba3 100644 --- a/library/src/main/ets/components/ImageKnifeComponent.ets +++ b/library/src/main/ets/components/ImageKnifeComponent.ets @@ -36,52 +36,62 @@ export struct ImageKnifeComponent { private componentVersion: number = 0 private currentContext: common.UIAbilityContext | undefined = undefined @Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption(); + @Monitor('imageKnifeOption', "imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit") watchImageKnifeOption() { - if (this.request !== undefined) { - this.request.requestState = ImageKnifeRequestState.DESTROY - } - this.request = undefined + this.clearLastRequest() this.componentVersion++ + this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit + LogUtil.log("watchImageKnifeOption execute request:width=" + this.currentWidth + " height= " + this.currentHeight + + " loadSrc = " + this.request?.imageKnifeOption.loadSrc + + " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc + + " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc) ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) } + aboutToAppear(): void { - //闪动问题失效,注释相应代码后续修复 - if(this.syncLoad) { + this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit + + if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题,建议使用同步方式在aboutToAppear时加载图片 let engineKey: IEngineKey = new DefaultEngineKey(); let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance() .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption)) if (memoryCacheSrc !== undefined){ - LogUtil.log("aboutToAppear load from memory cache for key = "+ engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption)) - //画主图 + LogUtil.log("aboutToAppear success load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc) this.pixelMap = memoryCacheSrc.source; - }else { - let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance() - .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption)) - if (memoryCachePlace !== undefined){ - LogUtil.log("aboutToAppear load from memory cache for key = "+ engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption)) - //画主图 - this.pixelMap = memoryCachePlace.source; + }else{ + LogUtil.log("aboutToAppear fail load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc) + if (this.imageKnifeOption.placeholderSrc !== undefined){ + let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance() + .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption)) + if (memoryCachePlace !== undefined){ + LogUtil.log("aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc) + this.pixelMap = memoryCachePlace.source; + }else{ + LogUtil.log("aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc) + } } } } - this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit } aboutToDisappear(): void { - if (this.request !== undefined) { - this.request.requestState = ImageKnifeRequestState.DESTROY - this.request = undefined - } + this.clearLastRequest() } aboutToRecycle() { + this.clearLastRequest() + } + + /** + * 对已DESTROY的组件不再发起请求 + */ + private clearLastRequest(){ if (this.request !== undefined) { this.request.requestState = ImageKnifeRequestState.DESTROY this.request = undefined } - this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit } build() { @@ -99,14 +109,15 @@ export struct ImageKnifeComponent { this.currentHeight = newValue.height as number this.lastWidth = oldValue.width as number this.lastHeight = oldValue.height as number - if (this.currentWidth <= 0 || this.currentHeight <= 0) { - // 存在宽或者高为0,此次重回无意义,无需进行request请求 - } else { - // 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制 - if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) { - LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight) - ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) - } + + // 条件1: 宽高值均有效,值>0. 条件2:当前宽高与上一次宽高不同 + if (this.currentWidth > 0 && this.currentHeight > 0 && + (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth)) { + LogUtil.log("onSizeChange execute request:width=" + this.currentWidth + " height= " + this.currentHeight + + " loadSrc = " + this.request?.imageKnifeOption.loadSrc + + " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc + + " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc) + ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight)) } }) } @@ -132,24 +143,10 @@ export struct ImageKnifeComponent { return //针对reuse场景,不显示历史图片 } this.pixelMap = pixelMap - if (typeof this.pixelMap !== 'string') { - if (this.imageKnifeOption.objectFit === ImageFit.Auto) { - let info = await this.pixelMap.getImageInfo() - - this.adaptiveWidth = this.currentWidth - this.adaptiveHeight = info.size.height * this.currentWidth / info.size.width - - // if (this.currentWidth / this.currentHeight > info.size.width / info.size.height) { - // this.adaptiveWidth = this.currentWidth - // this.adaptiveHeight = info.size.height * this.currentWidth / this.currentHeight - // } - // else { - // this.adaptiveWidth = info.size.width * this.currentWidth / this.currentHeight - // this.adaptiveHeight = this.currentHeight - // } - } - } else { - //console.info("KKKKKKKKKKK:" + pixelMap) + if (typeof this.pixelMap !== 'string' && this.imageKnifeOption.objectFit === ImageFit.Auto) { //针对静态图高度自适应 + let info = await this.pixelMap.getImageInfo() + this.adaptiveWidth = this.currentWidth + this.adaptiveHeight = info.size.height * this.currentWidth / info.size.width } if (requestSource == ImageKnifeRequestSource.SRC) { @@ -168,8 +165,4 @@ export struct ImageKnifeComponent { return this.request } -} - -interface KeyCanvas { - keyId: string } \ No newline at end of file