diff --git a/CHANGELOG.md b/CHANGELOG.md index e88d38d..2ff4129 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 2.2.0-rc.3 - 修复错误图绘制完后变成占位图 +- 提供图片加载成功/失败的事件 ## 2.2.0-rc.2 - ImageKnife支持下采样 diff --git a/README.md b/README.md index 9e03561..0c54b80 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataF | mainScaleType | ScaleType | 设置主图展示样式(可选) | | strategy | DiskStrategy | 设置磁盘缓存策略(可选) | | dontAnimateFlag | boolean | gif加载展示一帧(可选) | -| placeholderSrc | string\ (占位图不支持gif图且不支持网络下载功能) | PixelMap\ |Resource | 占位图数据源 | +| placeholderSrc | string\ (占位图不支持gif图且不支持网络下载功能) | PixelMap\ |Resource | 占位图数据源 | | placeholderScaleType | ScaleType | 设置占位图展示样式(可选) | | errorholderSrc | PixelMap\ | Resource | 错误占位图数据源 | | errorholderSrcScaleType | ScaleType | 设置失败占位图展示样式(可选) | @@ -177,7 +177,8 @@ ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataF | imageSmoothingEnabled | boolean | 抗锯齿是否开启属性配置,设置为false时,imageSmoothingQuality失效 | | imageSmoothingQuality | AntiAliasing | 抗锯齿属性配置 | | autoPlay | boolean | GIF播放暂停控制(可选) | -| customGetImage | (Context, string) | 设置是否使用应用自定义的方式加载图片(可选) | +| customGetImage | (Context, string) | 设置是否使用应用自定义的方式加载图片(可选) | +| onLoadListener | onLoadSuccess: (data: string | PixelMap | Resource | undefined) => void;onLoadFailed: (err: string) => void; | 监听图片加载成功/失败 | 其他参数只需要在ImageKnifeOption对象上按需添加即可。 diff --git a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets index 0bf0e66..0f07455 100644 --- a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets +++ b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets @@ -425,6 +425,14 @@ struct IndexFunctionDemo { router.pushUrl({ url: 'pages/testCustomDataFetchClientWithPage' }); }).margin({ top: 5, left: 3 }) }.width('100%').height(60).backgroundColor(Color.Pink) + + Text('测试监听加载成功/失败').fontSize(15) + Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Button('测试监听加载成功/失败') + .onClick(() => { + router.pushUrl({ url: 'pages/testImageKnifeLoadState' }); + }).margin({ top: 5, left: 3 }) + }.width('100%').height(60).backgroundColor(Color.Pink) } } .width('100%') diff --git a/entry/src/main/ets/pages/testImageKnifeLoadState.ets b/entry/src/main/ets/pages/testImageKnifeLoadState.ets new file mode 100644 index 0000000..8bea3f8 --- /dev/null +++ b/entry/src/main/ets/pages/testImageKnifeLoadState.ets @@ -0,0 +1,76 @@ +/* + * 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' + +@Entry +@Component +struct testImageKnifeCache { + @State imageKnifeOption: ImageKnifeOption = + { + loadSrc: $r('app.media.icon'), + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + }; + + build() { + Scroll() { + Column() { + Text('测试失败场景时关闭掉网络').fontSize(15); + Row() { + Button('测试加载成功/失败监听') + .onClick(() => { + this.imageKnifeOption = + { + loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + onLoadListener: { + onLoadSuccess: (data) => { + console.log('Load Successful: ' + data); + return data; + }, + onLoadFailed: (err) => { + console.error('Load Failed Reason: ' + err); + } + } + } + }) + } + + Text('网络图').fontSize(15); + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }) + .width(200) + .height(200) + .backgroundColor(Color.Orange) + } + .alignItems(HorizontalAlign.Center) + .width('100%') + } + .width('100%') + .height('100%') + } + + aboutToAppear() { + + } + + aboutToDisappear() { + + } + + onBackPress() { + + } +} \ No newline at end of file diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 057bcf6..61781a0 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -58,6 +58,7 @@ "pages/testImageKnifeNetPlaceholder", "pages/testCustomDataFetchClientWithPage", "pages/testReuseAblePages", - "pages/downsamplingPage" + "pages/downsamplingPage", + "pages/testImageKnifeLoadState" ] } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/List.test.ets b/entry/src/ohosTest/ets/test/List.test.ets index a2c71c5..ad551ac 100644 --- a/entry/src/ohosTest/ets/test/List.test.ets +++ b/entry/src/ohosTest/ets/test/List.test.ets @@ -22,6 +22,7 @@ import ImageKnifeTest from './imageknife.test' import DiskLruCacheTest from './diskLruCache.test' import SendableDataTest from './SendableData.test' import DefaultJobQueueTest from './DefaultJobQueueTest.test'; +import ImageKnifeOptionTest from './imageknifeOption.test'; export default function testsuite() { abilityTest() @@ -34,4 +35,5 @@ export default function testsuite() { SendableDataTest(); DefaultJobQueueTest(); CustomDataFetchClientTest(); + ImageKnifeOptionTest(); } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/imageknifeOption.test.ets b/entry/src/ohosTest/ets/test/imageknifeOption.test.ets new file mode 100644 index 0000000..21a0f19 --- /dev/null +++ b/entry/src/ohosTest/ets/test/imageknifeOption.test.ets @@ -0,0 +1,64 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { ImageKnifeOption } from '@ohos/imageknife' + +export default function ImageKnifeOptionTest() { + describe('ImageKnifeOptionTest', ()=> { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll( ()=> { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach( ()=> { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach( ()=> { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll( ()=> { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + it('onLoadListener',0, ()=> { + let a = 'abc'; + let b: string = ''; + let imageKnifeOption: ImageKnifeOption = { + loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658', + onLoadListener: { + onLoadSuccess: (data) => { + if (typeof data == 'string') { + b = data; + } + return data; + }, + onLoadFailed: (err) => { + console.log('Load Failed Reason: '+err); + } + } + } + if(imageKnifeOption.onLoadListener && imageKnifeOption.onLoadListener.onLoadSuccess && imageKnifeOption.onLoadListener.onLoadFailed) { + imageKnifeOption.onLoadListener.onLoadSuccess(a); + imageKnifeOption.onLoadListener.onLoadFailed(a); + } + expect(a).assertEqual(b); + }) + }) +} \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/ImageKnifeComponent.ets b/library/src/main/ets/components/imageknife/ImageKnifeComponent.ets index 7a31bc0..8ce6f3f 100644 --- a/library/src/main/ets/components/imageknife/ImageKnifeComponent.ets +++ b/library/src/main/ets/components/imageknife/ImageKnifeComponent.ets @@ -217,6 +217,23 @@ export struct ImageKnifeComponent { request.load(this.imageKnifeOption.loadSrc) .addListener({ callback: (err:BusinessError|string, data:ImageKnifeData) => { LogUtil.log('VISIBLE: ImageKnifeComponent request.load callback, err: ' + err); + if (err != "" && this.imageKnifeOption.onLoadListener && this.imageKnifeOption.onLoadListener.onLoadFailed) { + this.imageKnifeOption.onLoadListener.onLoadFailed(err as string); + } else if (err === "" && this.imageKnifeOption.onLoadListener && this.imageKnifeOption.onLoadListener.onLoadSuccess) { + let loadData: string | PixelMap | Resource | undefined = undefined; + if (data.isPixelMap() && data.drawPixelMap) { + loadData = data.drawPixelMap.imagePixelMap; + } else if (data.isGIFFrame() && data.drawGIFFrame && data.drawGIFFrame.imageGIFFrames) { + loadData = data.drawGIFFrame.imageGIFFrames.toString(); + } else if (data.isResource() && data.drawResource) { + loadData = data.drawResource.imageResource; + } else if (data.isString() && data.drawString) { + loadData = data.drawString.imageString; + } + if (loadData) { + this.imageKnifeOption.onLoadListener.onLoadSuccess(loadData); + } + } if(data.isGIFFrame()) { this.isGif = true } else { diff --git a/library/src/main/ets/components/imageknife/ImageKnifeOption.ets b/library/src/main/ets/components/imageknife/ImageKnifeOption.ets index bbd6278..f7a45b2 100644 --- a/library/src/main/ets/components/imageknife/ImageKnifeOption.ets +++ b/library/src/main/ets/components/imageknife/ImageKnifeOption.ets @@ -68,6 +68,10 @@ export interface HeaderOptions { key: string; value: string; } +export interface OnLoadCallBack { + onLoadSuccess?: (data: string | PixelMap | Resource | undefined) => void; + onLoadFailed?: (err: string) => void; +} @Observed export class ImageKnifeOption { @@ -152,6 +156,7 @@ export class ImageKnifeOption { // 设置是否使用应用自定义的方式加载图片 customGetImage?: (context: Context, src: string) => Promise; + onLoadListener?: OnLoadCallBack | undefined; constructor() { diff --git a/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets b/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets index c54f6e5..1990ec3 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets @@ -67,8 +67,6 @@ export class HttpDownloadClient implements IDataFetch { }) if ( data == 200) { result.data = this.combineArrayBuffers(arrayBuffers); - } else { - result.error = `HttpDownloadClient has error, http code = ` + JSON.stringify(data); } console.log('TestCustomDataFetch http onComplete, code = ' + data + ',length = ' + result.data?.byteLength); } catch (err) {