diff --git a/README.md b/README.md index 5cd4314..3628364 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,40 @@ imageKnifeOption = { ### 6.自定义请求头规格 设置全局header并且设置request的header时,当key不同时全局和request并行,当key相同时request的header覆盖全局的header +### 7.自定义网络栈加载图片 +7.1 自定义网络栈加载单个图片,在imageKnifeNextOption中添加customGetImage标签,然后完善custom函数的逻辑即可, +``` +ImageKnifeNextComponent({ + imageKnifeNextOption: { + loadSrc: 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg', + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + customGetImage: custom + } +}).width(100).height(100) + +// 自定义实现图片获取方法,如自定义网络下载 +@Concurrent +async function custom(context: Context, src: string): Promise { + let result: DataFetchResult = new DataFetchResult(); + result.data = arraybuffer; //此处替换成自己网络获取的ArrayBuffer的逻辑 + return result; +} +``` +7.2 自定义网络栈加载全部图片 +``` +1.先执行ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataFetchClient()); 替换网络栈 +2.在CustomDataFetchClient这个类中也通过下面的逻辑替换成自己网络获取的ArrayBuffer的逻辑 + let result: DataFetchResult = new DataFetchResult(); + result.data = arraybuffer; //此处替换成自己网络获取的ArrayBuffer的逻辑 + return result; +``` +7.3 取消自定义网络栈加载全部图片 +``` +如果用户执行了自定义网络加载全部图片,后面又不想自定义网络栈加载全部图片了,可以通过下面的方式恢复 +ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataFetchClient()); +``` + ## 进阶使用 如果简单的加载一张图像无法满足需求,我们可以看看ImageKnifeOption这个类提供了哪些扩展能力。 @@ -143,6 +177,7 @@ imageKnifeOption = { | imageSmoothingEnabled | boolean | 抗锯齿是否开启属性配置,设置为false时,imageSmoothingQuality失效 | | imageSmoothingQuality | AntiAliasing | 抗锯齿属性配置 | | autoPlay | boolean | GIF播放暂停控制(可选) | +| customGetImage | (Context, string) | 设置是否使用应用自定义的方式加载图片(可选) | 其他参数只需要在ImageKnifeOption对象上按需添加即可。 @@ -537,6 +572,7 @@ HSP场景适配: - storageTestDiskLruCache.ets # 磁盘缓存测试 - storageTestLruCache.ets # 内存缓存测试 - testAllCacheInfoPage.ets # 所有缓存信息获取测试 + - testCustomDataFetchClientWithPage # 测试图片下载使用自定义的网络栈 - testImageKnifeAutoHeightPage.ets # 图片高度自适应测试 - testImageKnifeAutoWidthPage.ets # 图片宽度自适应测试 - testImageKnifeAutoPage.ets # 图片宽高自适应测试 diff --git a/entry/src/main/ets/pages/testCustomDataFetchClientWithPage.ets b/entry/src/main/ets/pages/testCustomDataFetchClientWithPage.ets index c2a82f0..be10b30 100644 --- a/entry/src/main/ets/pages/testCustomDataFetchClientWithPage.ets +++ b/entry/src/main/ets/pages/testCustomDataFetchClientWithPage.ets @@ -79,6 +79,8 @@ struct TestCustomDataFetchClientWithPage { @State isSingleImageVisible: boolean = true; @State isAllImageVisible: boolean = false; @State isCustom: boolean = false; + private isAllImageAdded: boolean = false; + private isCancelImageAdded: boolean = false; private data: Array = [ "http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg", "http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg" @@ -107,7 +109,6 @@ struct TestCustomDataFetchClientWithPage { LogUtil.log('TestCustomDataFetch click single.'); this.isSingleImageVisible = true; this.isAllImageVisible = false; - ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataFetchClient()); this.singleImageKnifeOption = { loadSrc: 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg', @@ -122,8 +123,10 @@ struct TestCustomDataFetchClientWithPage { this.isAllImageVisible = true; ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataFetchClient()); - this.hotCommendList.addData(this.hotCommendList.totalCount(), this.addData) - + if (!this.isAllImageAdded) { + this.hotCommendList.addData(this.hotCommendList.totalCount(), this.addData); + this.isAllImageAdded = true; + } }) Button("取消自定义全部图片").margin(16).onClick(() => { @@ -132,7 +135,10 @@ struct TestCustomDataFetchClientWithPage { this.isAllImageVisible = true; ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new DownloadClient()); - this.hotCommendList.addData(this.hotCommendList.totalCount(), this.cancelData) + if (!this.isCancelImageAdded) { + this.hotCommendList.addData(this.hotCommendList.totalCount(), this.cancelData); + this.isCancelImageAdded = true; + } }) } diff --git a/entry/src/ohosTest/ets/test/List.test.ets b/entry/src/ohosTest/ets/test/List.test.ets index 9d986c8..a2c71c5 100644 --- a/entry/src/ohosTest/ets/test/List.test.ets +++ b/entry/src/ohosTest/ets/test/List.test.ets @@ -14,6 +14,7 @@ */ import abilityTest from './Ability.test' import lruCacheTest from './lrucache.test' +import CustomDataFetchClientTest from './customdatafetchclient.test' import LogUtilTest from './logutil.test' import Transfrom from './transfrom.test' import RequestOptionTest from './requestoption.test' @@ -32,4 +33,5 @@ export default function testsuite() { ImageKnifeTest(); SendableDataTest(); DefaultJobQueueTest(); + CustomDataFetchClientTest(); } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/customdatafetchclient.test.ets b/entry/src/ohosTest/ets/test/customdatafetchclient.test.ets new file mode 100644 index 0000000..38109e7 --- /dev/null +++ b/entry/src/ohosTest/ets/test/customdatafetchclient.test.ets @@ -0,0 +1,106 @@ +/* + * 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 { DownloadClient } from '@ohos/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient'; +import common from '@ohos.app.ability.common'; +import { GlobalContext } from '../testability/GlobalContext'; +import { CustomDataFetchClient, DataFetchResult, ImageKnifeGlobal, RequestOption } from '@ohos/imageknife'; + +const BASE_COUNT: number = 2000; + +export default function CustomDataFetchClientTest() { + describe('CustomDataFetchClientTest', () => { + // 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('TestIsLocalLoadSrc', 0, () => { + let path = 'invalid path'; + let client = new DownloadClient() + expect(client.isLocalLoadSrc(undefined, path)).assertFalse(); + let context: object | undefined = GlobalContext.getInstance().getObject("hapContext"); + if (context != undefined) { + let loadSrc1 = (context as common.UIAbilityContext).filesDir + 'a.jpg'; + let loadSrc2 = (context as common.UIAbilityContext).cacheDir + 'b.jpg'; + expect(client.isLocalLoadSrc(context, loadSrc1)).assertTrue(); + expect(client.isLocalLoadSrc(context, loadSrc2)).assertTrue(); + } + }) + it('TestLoadData', 1, async () => { + let client = new CustomDataFetchClient(); + let request = new RequestOption(); + request.loadSrc = $r('app.media.icon'); + let error = (await client.loadData(request) as DataFetchResult).error as String; + expect(error).assertEqual('CustomDataFetchClient request or loadSrc error.'); + }) + it('TestLoadData_customGetImage', 2, async () => { + let client = new CustomDataFetchClient(); + let request = new RequestOption(); + request.loadSrc = 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg'; + request.customGetImage = (context: Context, src: string) => { + // 这里是模拟的customGetImage逻辑 + return Promise.resolve(new DataFetchResult()); + } + console.log('LXH', 'TestLoadData 2 --1 customGetImage is undefined ?' + (request.customGetImage == undefined)); + let context: object | undefined = GlobalContext.getInstance().getObject("hapContext"); + let result = await client.loadData(request); + if (context != undefined) { + console.log('LXH', 'TestLoadData 2 --2'); + expect(typeof result) + .assertEqual(typeof (await request?.customGetImage(context as common.UIAbilityContext, request.loadSrc))); + } + }) + it('TestLoadData_combineArrayBuffers', 3, () => { + // 创建几个ArrayBuffer作为测试数据 + const arrayBuffer1 = new ArrayBuffer(4); + const uint8Array1 = new Uint8Array(arrayBuffer1); + uint8Array1[0] = 1; + uint8Array1[1] = 2; + uint8Array1[2] = 3; + uint8Array1[3] = 4; + + const arrayBuffer2 = new ArrayBuffer(2); + const uint8Array2 = new Uint8Array(arrayBuffer2); + uint8Array2[0] = 5; + uint8Array2[1] = 6; + let client = new CustomDataFetchClient(); + const combinedArrayBuffer = client.combineArrayBuffers([arrayBuffer1, arrayBuffer2]); + expect(combinedArrayBuffer.byteLength).assertEqual(6); + const combinedUint8Array = new Uint8Array(combinedArrayBuffer); + for (let i = 0; i < 4; i++) { + expect(combinedUint8Array[i]).assertEqual(uint8Array1[i]); + } + for (let i = 0; i < 2; i++) { + expect(combinedUint8Array[i + 4]).assertEqual(uint8Array2[i]); + } + }); + }) +} + diff --git a/library/src/main/ets/components/imageknife/networkmanage/CustomDataFetchClient.ets b/library/src/main/ets/components/imageknife/networkmanage/CustomDataFetchClient.ets index db50dd1..95a7283 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/CustomDataFetchClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/CustomDataFetchClient.ets @@ -29,11 +29,6 @@ export class CustomDataFetchClient implements IDataFetch { result.error = 'CustomDataFetchClient request or loadSrc error.'; return result; } - // 自定义单个图片的网络栈 - if (request.customGetImage) { - return await request.customGetImage(ImageKnifeGlobal.getInstance() - .getHapContext() as common.UIAbilityContext, request.loadSrc); - } // 所有图片的网络栈 try { let httpRequest = http.createHttp() diff --git a/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets b/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets index c769b17..59aa744 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets @@ -35,7 +35,10 @@ export class DownloadClient implements IDataFetch { async loadData(request: RequestOption): Promise { if (typeof request.loadSrc == 'string') { - if (this.isLocalLoadSrc(ImageKnifeGlobal.getInstance().getHapContext(), request.loadSrc)) { + if (request.customGetImage) { + return await request.customGetImage(ImageKnifeGlobal.getInstance() + .getHapContext() as common.UIAbilityContext, request.loadSrc); + } else if (this.isLocalLoadSrc(ImageKnifeGlobal.getInstance().getHapContext(), request.loadSrc)) { // 本地沙盒 return this.localFileClient.loadData(request) } else if (request.loadSrc.startsWith('datashare://') || request.loadSrc.startsWith('file://')) {