From 3d4493912a1ea4081dadae7bcbe8d7041a4796f3 Mon Sep 17 00:00:00 2001 From: zgf Date: Wed, 16 Oct 2024 10:49:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A2=84=E5=8A=A0=E8=BD=BDpr?= =?UTF-8?q?eload=E3=80=81=E5=8F=96=E6=B6=88=E5=8A=A0=E8=BD=BDcancel?= =?UTF-8?q?=E3=80=81=E9=87=8D=E8=AF=95=E5=8A=A0=E8=BD=BDreload=E5=92=8C?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E7=BD=91=E7=BB=9C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=A4=B4=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zgf --- CHANGELOG.md | 5 + README_zh.md | 52 +-- entry/src/main/ets/pages/ImageKnifeReload.ets | 82 ++++ entry/src/main/ets/pages/Index.ets | 10 + entry/src/main/ets/pages/LazyForEachCache.ets | 51 +++ entry/src/main/ets/pages/LazyForEachCount.ets | 51 +++ .../main/ets/pages/PrefetchAndCacheCount.ets | 39 ++ .../src/main/ets/pages/PrefetchAndPreload.ets | 56 +++ entry/src/main/ets/pages/SingleImage.ets | 9 +- entry/src/main/ets/pages/UserPage.ets | 41 +- .../main/ets/pages/model/CommonDataSource.ets | 54 +++ .../ets/pages/model/DataSourcePrefetching.ets | 93 +++++ .../main/ets/pages/model/PageViewModel.ets | 146 +++++++ entry/src/main/module.json5 | 9 + .../main/resources/base/element/string.json | 8 + .../resources/base/profile/main_pages.json | 7 +- .../main/resources/en_US/element/string.json | 356 ++++++++++++++++++ .../main/resources/zh_CN/element/string.json | 8 + library/oh-package.json5 | 2 +- library/src/main/ets/ImageKnife.ets | 49 ++- library/src/main/ets/ImageKnifeDispatcher.ets | 2 +- library/src/main/ets/ImageKnifeLoader.ets | 29 +- library/src/main/ets/model/ImageKnifeData.ets | 2 +- .../src/main/ets/model/ImageKnifeOption.ets | 5 +- 24 files changed, 1078 insertions(+), 88 deletions(-) create mode 100644 entry/src/main/ets/pages/ImageKnifeReload.ets create mode 100644 entry/src/main/ets/pages/LazyForEachCache.ets create mode 100644 entry/src/main/ets/pages/LazyForEachCount.ets create mode 100644 entry/src/main/ets/pages/PrefetchAndCacheCount.ets create mode 100644 entry/src/main/ets/pages/PrefetchAndPreload.ets create mode 100644 entry/src/main/ets/pages/model/CommonDataSource.ets create mode 100644 entry/src/main/ets/pages/model/DataSourcePrefetching.ets create mode 100644 entry/src/main/ets/pages/model/PageViewModel.ets diff --git a/CHANGELOG.md b/CHANGELOG.md index 794a2f7..8032e0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.1.1-rc.1 +- Added new image reloading interface reload +- Added return request preload interface preload +- Added cancel request interface cancel +- Custom network method to add request header parameters ## 3.1.1-rc.0 - 重构代码:抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中,降低函数复杂度 diff --git a/README_zh.md b/README_zh.md index 97522da..235ec7d 100644 --- a/README_zh.md +++ b/README_zh.md @@ -287,27 +287,27 @@ ImageKnifeAnimatorComponent({ ### ImageKnifeOption参数列表 -| 参数名称 | 入参内容 | 功能简介 | -|-----------------------|-------------------------------------------------------|-----------------| -| loadSrc | string、PixelMap、Resource | 主图展示 | -| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) | -| errorholderSrc | PixelMap、Resource | 错误图展示(可选) | -| objectFit | ImageFit | 主图填充效果(可选) | -| placeholderObjectFit | ImageFit | 占位图填充效果(可选) | -| errorholderObjectFit | ImageFit | 错误图填充效果(可选) | -| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) | -| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) | -| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 | -| border | BorderOptions | 边框圆角(可选) | -| priority | taskpool.Priority | 加载优先级(可选) | -| context | common.UIAbilityContext | 上下文(可选) | -| progressListener | (progress: number)=>void | 进度(可选) | -| signature | String | 自定义缓存关键字(可选) | -| headerOption | Array | 设置请求头(可选) | -| transformation | PixelMapTransformation | 图片变换(可选) | -| drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) | -| onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) | -| onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 | +| 参数名称 | 入参内容 | 功能简介 | +|-----------------------|----------------------------------------------------------------------------------------------------------------------|-----------------| +| loadSrc | string、PixelMap、Resource | 主图展示 | +| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) | +| errorholderSrc | PixelMap、Resource | 错误图展示(可选) | +| objectFit | ImageFit | 主图填充效果(可选) | +| placeholderObjectFit | ImageFit | 占位图填充效果(可选) | +| errorholderObjectFit | ImageFit | 错误图填充效果(可选) | +| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) | +| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) | +| customGetImage | (context: Context, src: string、PixelMap、Resource,headers?: Record) => Promise| 自定义下载图片(可选) | | Resource | 错误占位图数据源 | +| border | BorderOptions | 边框圆角(可选) | +| priority | taskpool.Priority | 加载优先级(可选) | +| context | common.UIAbilityContext | 上下文(可选) | +| progressListener | (progress: number)=>void | 进度(可选) | +| signature | String | 自定义缓存关键字(可选) | +| headerOption | Array | 设置请求头(可选) | +| transformation | PixelMapTransformation | 图片变换(可选) | +| drawingColorFilter | ColorFilter、drawing.ColorFilter | 图片变换(可选) | +| onComplete | (event:EventImage、undefined) => voi | 颜色滤镜效果(可选) | +| onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string、PixelMap、undefined) => void、onLoadFailed: (err: string) => void | 监听图片加载成功与失败 | ### ImageKnife接口 @@ -316,15 +316,19 @@ ImageKnifeAnimatorComponent({ | initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 | | initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | | preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 | +| reload | request: ImageKnifeRequest | 图片重新加载 | +| preLoad | loadSrc: string I ImageKnifeOption | 预加载返回图片请求request | +| cancel | request: ImageKnifeRequest | 取消图片请求 | +| preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 | | getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 | | addHeader | key: string, value: Object | 全局添加http请求头 | | setHeaderOptions | Array | 全局设置http请求头 | | deleteHeader | key: string | 全局删除http请求头 | -| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise | 全局设置自定义下载 | +| setCustomGetImage | customGetImage?: (context: Context, src: string、PixelMap、Resource,headers?: Record) => Promise | 全局设置自定义下载 | | setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | | putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | -| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 | -| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 | +| removeMemoryCache| url: string、ImageKnifeOption | 清理指定内存缓存 | +| removeFileCache | url: string、ImageKnifeOption | 清理指定磁盘缓存 | ### 图形变换类型(需要为GPUImage添加依赖项) | 类型 | 相关描述 | diff --git a/entry/src/main/ets/pages/ImageKnifeReload.ets b/entry/src/main/ets/pages/ImageKnifeReload.ets new file mode 100644 index 0000000..6f9b72b --- /dev/null +++ b/entry/src/main/ets/pages/ImageKnifeReload.ets @@ -0,0 +1,82 @@ +/* + * 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 { connection } from '@kit.NetworkKit' +import { List } from '@kit.ArkTS' +import { ImageKnifeRequest,ImageKnife,ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' + +@Entry +@Component +struct ImageKnifeReload { + aboutToAppear(): void { + NetWatchState.init() + } + build() { + Column() { + ImageKnifeComponent({ + imageKnifeOption:new ImageKnifeOption({ + loadSrc:"https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp", + placeholderSrc:$r('app.media.loading'), + errorholderSrc:$r('app.media.failed'), + onLoadListener:{ + onLoadFailed(err,request){ + NetWatchState.requestList.add(request) + } + } + }) + }).width(200).height(200) + ImageKnifeComponent({ + imageKnifeOption:new ImageKnifeOption({ + loadSrc:"https://img-blog.csdn.net/20140514114029140", + placeholderSrc:$r('app.media.loading'), + errorholderSrc:$r('app.media.failed'), + onLoadListener:{ + onLoadFailed(err,request){ + NetWatchState.requestList.add(request) + } + } + }) + }).width(200).height(200).margin({top:10}) + }.width("100%") + .height("100%") + } +} + +class NetWatchState { + public static netConnection: connection.NetConnection | undefined = undefined + public static requestList: List = new List() + + static init() { + NetWatchState.netConnection = connection.createNetConnection() + // 注册订阅事件 + NetWatchState.netConnection.register(()=>{ + }) + // 订阅网络能力变化事件。调用register后,才能接收到此事件通知 + NetWatchState.netConnection.on("netCapabilitiesChange",(data:connection.NetCapabilityInfo)=>{ + if(NetWatchState.requestList.length > 0 && data.netHandle.netId >= 100) { + NetWatchState.requestList.forEach((request)=>{ + ImageKnife.getInstance().reload(request) + NetWatchState.requestList.remove(request) + }) + } + }) + } + + static cancel(){ + if(NetWatchState.netConnection != undefined) { + // 取消订阅 + NetWatchState.netConnection.unregister(()=>{}) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 75fa2f2..169d04a 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -35,6 +35,16 @@ struct Index { uri: 'pages/ImageAnimatorPage', }); }) + Button($r('app.string.preloading_prefetch')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/PrefetchAndCacheCount', + }); + }) + Button($r('app.string.Network_reload')).margin({top:10}).onClick(()=>{ + router.push({ + uri: 'pages/ImageKnifeReload', + }); + }) Button($r('app.string.Test_multiple_images')).margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/TestCommonImage', diff --git a/entry/src/main/ets/pages/LazyForEachCache.ets b/entry/src/main/ets/pages/LazyForEachCache.ets new file mode 100644 index 0000000..0cc3668 --- /dev/null +++ b/entry/src/main/ets/pages/LazyForEachCache.ets @@ -0,0 +1,51 @@ +/* + * 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 { InfoItem } from './model/DataSourcePrefetching'; +import { PageViewModel } from './model/PageViewModel'; +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +export struct LazyForEachCache { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + aboutToAppear(): void { + this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems()) + } + build() { + Column() { + List({ space: 16 }) { + LazyForEach(this.hotCommendList, (item: InfoItem,index) => { + ListItem() { + Column({ space: 12 }) { + ImageKnifeComponent({ + imageKnifeOption:new ImageKnifeOption({ + loadSrc: item.albumUrl, + placeholderSrc:$r('app.media.loading') + }) + }).width(100).height(100) + Text(`${index}`) + }.border({ width: 5 , color: "#000000"}) + } + }) + } + .cachedCount(5) + .width("100%") + .height("100%") + .margin({ left: 10, right: 10 }) + .layoutWeight(1) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/LazyForEachCount.ets b/entry/src/main/ets/pages/LazyForEachCount.ets new file mode 100644 index 0000000..5767a14 --- /dev/null +++ b/entry/src/main/ets/pages/LazyForEachCount.ets @@ -0,0 +1,51 @@ +/* + * 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 { InfoItem } from './model/DataSourcePrefetching'; +import { PageViewModel } from './model/PageViewModel'; +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; +import { CommonDataSource } from './model/CommonDataSource'; + +@Entry +@Component +export struct LazyForEachCount { + @State hotCommendList:CommonDataSource = new CommonDataSource([]) + aboutToAppear(): void { + this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems()) + } + build() { + Column() { + List({ space: 16 }) { + LazyForEach(this.hotCommendList, (item: InfoItem,index) => { + ListItem() { + Column({ space: 12 }) { + ImageKnifeComponent({ + imageKnifeOption:new ImageKnifeOption({ + loadSrc: item.albumUrl, + placeholderSrc:$r('app.media.loading') + }) + }).width(100).height(100) + Text(`${index}`) + }.border({ width: 5 , color: "#000000"}) + } + }) + } + .cachedCount(30) + .width("100%") + .height("100%") + .margin({ left: 10, right: 10 }) + .layoutWeight(1) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/PrefetchAndCacheCount.ets b/entry/src/main/ets/pages/PrefetchAndCacheCount.ets new file mode 100644 index 0000000..00c3f08 --- /dev/null +++ b/entry/src/main/ets/pages/PrefetchAndCacheCount.ets @@ -0,0 +1,39 @@ +/* + * 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 { router } from '@kit.ArkUI' + +@Entry +@Component +struct PrefetchAndCacheCount { + build() { + Column() { + Button("cacheCount == 5") + .onClick(()=>{ + router.pushUrl({url:"pages/LazyForEachCache"}) + }) + Button("cacheCount == 30") + .margin({top:10}) + .onClick(()=>{ + router.pushUrl({url:"pages/LazyForEachCount"}) + }) + Button("prefetch + preload") + .margin({top:10}) + .onClick(()=>{ + router.pushUrl({url:"pages/PrefetchAndPreload"}) + }) + }.width("100%") + .height("100%") + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/PrefetchAndPreload.ets b/entry/src/main/ets/pages/PrefetchAndPreload.ets new file mode 100644 index 0000000..a66793e --- /dev/null +++ b/entry/src/main/ets/pages/PrefetchAndPreload.ets @@ -0,0 +1,56 @@ +/* + * 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 { BasicPrefetcher } from '@kit.ArkUI'; +import DataSourcePrefetchingImageKnife, { InfoItem } from './model/DataSourcePrefetching'; +import { PageViewModel } from './model/PageViewModel'; +import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; +@Entry +@Component +export struct PrefetchAndPreload { + // 创建DataSourcePrefetchingImageKnife对象,具备任务预取、取消能力的数据源 + private readonly dataSource = new DataSourcePrefetchingImageKnife(PageViewModel.getItems()); + // 创建BasicPrefetcher对象,默认的动态预取算法实现 + private readonly prefetcher = new BasicPrefetcher(this.dataSource); + + build() { + Column() { + List({ space: 16 }) { + LazyForEach(this.dataSource, (item: InfoItem,index:number) => { + ListItem() { + Column({ space: 12 }) { + ImageKnifeComponent({ + imageKnifeOption:new ImageKnifeOption({ + loadSrc: item.albumUrl, + placeholderSrc:$r('app.media.loading') + }) + }).width(100).height(100) + Text(`${index}`) + }.border({ width: 5 , color: "#000000"}) + } + .reuseId('imageKnife') + }) + } + .cachedCount(5) + .onScrollIndex((start: number, end: number) => { + // 列表滚动触发visibleAreaChanged,实时更新预取范围,触发调用prefetch、cancel接口 + this.prefetcher.visibleAreaChanged(start, end) + }) + .width("100%") + .height("100%") + .margin({ left: 10, right: 10 }) + .layoutWeight(1) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/SingleImage.ets b/entry/src/main/ets/pages/SingleImage.ets index 3671c6c..eaec4d7 100644 --- a/entry/src/main/ets/pages/SingleImage.ets +++ b/entry/src/main/ets/pages/SingleImage.ets @@ -88,6 +88,10 @@ struct SingleImage { placeholderSrc: $r("app.media.loading"), errorholderSrc: $r("app.media.failed"), objectFit: ImageFit.Contain, + headerOption:[{ + key:"refer", + value:"xx.xx.xx.xx" + }], customGetImage: custom, transformation: new BlurTransformation(10) }) @@ -124,8 +128,9 @@ struct SingleImage { // 自定义下载方法 @Concurrent -async function custom(context: Context, src: string | PixelMap | Resource): Promise { - console.info("ImageKnife:: custom download:" + src) +async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record): Promise { + let refer = headers!["refer"] as string + console.info("ImageKnife:: custom download:" + src,"refer:"+refer) // 举例写死从本地文件读取,也可以自己请求网络图片 return context.resourceManager.getMediaContentSync($r("app.media.startIcon").id).buffer as ArrayBuffer } diff --git a/entry/src/main/ets/pages/UserPage.ets b/entry/src/main/ets/pages/UserPage.ets index 92d1caf..ab13a6b 100644 --- a/entry/src/main/ets/pages/UserPage.ets +++ b/entry/src/main/ets/pages/UserPage.ets @@ -12,48 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { CommonDataSource } from './model/CommonDataSource' import { MyStorage, UserAvatar } from './User' -class CommonDataSource implements IDataSource { - private dataArray: T[] = [] - private listeners: DataChangeListener[] = [] - - constructor(element: []) { - this.dataArray = element - } - - public getData(index: number) { - return this.dataArray[index] - } - - public totalCount(): number { - return this.dataArray.length - } - - public addData(index: number, data: T[]): void { - this.dataArray = this.dataArray.concat(data) - this.notifyDataAdd(index) - } - - unregisterDataChangeListener(listener: DataChangeListener): void { - const pos = this.listeners.indexOf(listener); - if (pos >= 0) { - this.listeners.splice(pos, 1); - } - } - - registerDataChangeListener(listener: DataChangeListener): void { - if (this.listeners.indexOf(listener) < 0) { - this.listeners.push(listener) - } - } - - notifyDataAdd(index: number): void { - this.listeners.forEach((listener: DataChangeListener) => { - listener.onDataAdd(index) - }) - } -} @Entry @ComponentV2 struct Index { diff --git a/entry/src/main/ets/pages/model/CommonDataSource.ets b/entry/src/main/ets/pages/model/CommonDataSource.ets new file mode 100644 index 0000000..d6b16c0 --- /dev/null +++ b/entry/src/main/ets/pages/model/CommonDataSource.ets @@ -0,0 +1,54 @@ +/* + * 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. + */ +export class CommonDataSource implements IDataSource { + private dataArray: T[] = [] + private listeners: DataChangeListener[] = [] + + constructor(element: []) { + this.dataArray = element + } + + public getData(index: number) { + return this.dataArray[index] + } + + public totalCount(): number { + return this.dataArray.length + } + + public addData(index: number, data: T[]): void { + this.dataArray = this.dataArray.concat(data) + this.notifyDataAdd(index) + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener) + } + } + + notifyDataAdd(index: number): void { + this.listeners.forEach((listener: DataChangeListener) => { + listener.onDataAdd(index) + }) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/model/DataSourcePrefetching.ets b/entry/src/main/ets/pages/model/DataSourcePrefetching.ets new file mode 100644 index 0000000..07e0101 --- /dev/null +++ b/entry/src/main/ets/pages/model/DataSourcePrefetching.ets @@ -0,0 +1,93 @@ +/* + * 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 {ImageKnife, ImageKnifeRequest} from "@ohos/libraryimageknife" +import { IDataSourcePrefetching } from '@kit.ArkUI'; +import { HashMap } from '@kit.ArkTS'; + +const IMADE_UNAVAILABLE = $r('app.media.failed') +export interface InfoItem { + albumUrl: string | Resource +} +export default class DataSourcePrefetchingImageKnife implements IDataSourcePrefetching { + private dataArray: Array + private readonly requestList: HashMap = new HashMap() + private listeners: DataChangeListener[] = []; + + constructor(dataArray: Array) { + this.dataArray = dataArray; + } + public getData(index: number) { + return this.dataArray[index] + } + + public totalCount(): number { + return this.dataArray.length + } + + public addData(index: number, data: InfoItem[]): void { + this.dataArray = this.dataArray.concat(data) + this.notifyDataAdd(index) + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener) + } + } + + notifyDataAdd(index: number): void { + this.listeners.forEach((listener: DataChangeListener) => { + listener.onDataAdd(index) + }) + } + async prefetch(index: number): Promise { + let item = this.dataArray[index] + if (typeof item.albumUrl == "string") { + // 图片预加载 + let request = ImageKnife.getInstance().preload({ + loadSrc:item.albumUrl, + onLoadListener:{ + onLoadSuccess:()=>{ + // 预加载成功,删除成功请求 + this.requestList.remove(index) + }, + onLoadFailed:()=>{ + // 移除失败请求 + this.requestList.remove(index) + } + } + }) + this.requestList.set(index,request) + } + } + // 取消请求处理 + cancel(index: number) { + if(this.requestList.hasKey(index)) { + // 返回MAP对象指定元素 + const request = this.requestList.get(index) + // 取消请求 + ImageKnife.getInstance().cancel(request) + // 移除被取消的请求对象 + this.requestList.remove(index) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/model/PageViewModel.ets b/entry/src/main/ets/pages/model/PageViewModel.ets new file mode 100644 index 0000000..7a33e3a --- /dev/null +++ b/entry/src/main/ets/pages/model/PageViewModel.ets @@ -0,0 +1,146 @@ +/* + * 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 { InfoItem } from './DataSourcePrefetching' + +export class PageViewModel { + private static dataArray: Array = [ + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/42/v3/2dSQCqERTP2TTPyssOMEbQ/zL1ebnKKQ_ilqTDcwCAkOw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/8a/v3/ZKzYV5BJTuCk5hCE0y_xNA/8JT95OQnSZSd6_xQQUONhQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/1/v3/sTXb_I7URBKjdMyLDYa19w/qpcwa_FNQmi3-EzjbGsJ8A.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e5/v3/m7wFvw_eQIuDV0Mk0IKi8g/gJU4migzTHKYk5KrgdZbBw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3f/v3/k_UWbB5_RGW7JemQZ0OQdw/_DUdmaZRQyG-Oyvkb663Bw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/39/v3/rFRN7G_VSo-p4mBjTZtkRw/gBwTI-ieSIqSsSmLNBEcgw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/04/v3/6K8BPYKVQFOr7KCuAG9nog/qKd3pZlrQy2M-feB3ycVPA.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/7d/v3/f0GQFzm1T6eduVeMUhO3Wg/-4cvzIJiRCegjIno3ofIbQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e4/v3/C0xxsSeySxW-2iYR5OEbpQ/f1GlaD3zTeKPX8Vd-M1oVQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/c2/v3/32LCyXN4TuWKWcdf9gAwWw/ej14_BCJQNCaWOKoI9aZAw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fd/v3/LyYJMdMmQNaC5GyBYEZ5Pw/uFLiovypRSagKyIS-UJPVw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/15/v3/MHM9KaWGTgubn6M8-B_6nw/1YO9JyYhTHSBWsoiqYkGZw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/4c/v3/UdYfbv1_QYqn_ulDHp89OA/VkjexMluTqGO3yt3gPK1DA.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e8/v3/N8blT_7qSK-tRtahIyov7g/M_kjGEEmSzOlTc47Zrfozg.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/28/v3/VS_h3m4YRrSgbgxnqE3vtQ/h-2Q1Qy2SSGEuXM36-Rq_w.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/2e/v3/R-BaM5ToRNGq5rwtNTcnww/Q2e01VHiR2y9KtFaZmpmNQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/88/v3/3djkAJKKTdC539XqMdstSg/wHO7DxvXQS2xbt2Y_-4BNg.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/guw4eiggR3uWjscFTxITYg/TzRB35iPTdCztrZUUaNuFg.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/93/v3/UvSh_f1LT66i0-3hvsYN_A/eYnE3Z8YT5Sk7F-vS2ZmCQ.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/5/v3/tv8Vqf9hQrKpozGeZWg2mw/VEICB-bmQYi0Iv6TGADbhw.jpg" + }, + { + albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/4v1Ot5BRR6OFVQ9MGn9Xxg/xrPgRn0LS1ep-r7ewIuwiw.jpg" + }, + ] + static getItems() { + return PageViewModel.dataArray + } +} \ No newline at end of file diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index 6c284c7..a493443 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -42,6 +42,15 @@ ], "when": "always" } + }, + { + "name": "ohos.permission.GET_NETWORK_INFO", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "always" + } } ] } diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json index f982e81..4d62c27 100644 --- a/entry/src/main/resources/base/element/string.json +++ b/entry/src/main/resources/base/element/string.json @@ -367,6 +367,14 @@ { "name": "TIPS", "value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally" + }, + { + "name": "Network_reload", + "value": "Network recovery reload" + }, + { + "name": "preloading_prefetch", + "value": "Dynamic preloading prefetch" } ] } \ 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 d42cd2d..224d7cc 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -22,6 +22,11 @@ "pages/ImageAnimatorPage", "pages/TestSetCustomImagePage", "pages/TestErrorHolderPage", - "pages/TestTaskResourcePage" + "pages/TestTaskResourcePage", + "pages/LazyForEachCount", + "pages/LazyForEachCache", + "pages/PrefetchAndCacheCount", + "pages/PrefetchAndPreload", + "pages/ImageKnifeReload" ] } \ No newline at end of file diff --git a/entry/src/main/resources/en_US/element/string.json b/entry/src/main/resources/en_US/element/string.json index 13c1fec..4d62c27 100644 --- a/entry/src/main/resources/en_US/element/string.json +++ b/entry/src/main/resources/en_US/element/string.json @@ -19,6 +19,362 @@ { "name": "app_permission_READ_IMAGEVIDEO", "value": "获取读媒体资源权限" + }, + { + "name": "Test_ImageAnimator", + "value": "Test ImageAnimator component" + }, + { + "name": "Test_multiple_images", + "value": "Test loading multiple identical images" + }, + { + "name": "Test_Task_error", + "value": "Test placeholder map Task error" + }, + { + "name": "Test_HSP", + "value": "Test HSP scene preloading" + }, + { + "name": "Test_SingleImage", + "value": "SingleImage" + }, + { + "name": "Test_custom_download", + "value": "Global custom download" + }, + { + "name": "Multiple_images", + "value": "Multiple images" + }, + { + "name": "Display_long_image", + "value": "Display long image" + }, + { + "name": "Image_scaling", + "value": "Image scaling" + }, + { + "name": "Message_list", + "value": "Message list" + }, + { + "name": "Custom_cache_key", + "value": "Custom cache key" + }, + { + "name": "Preloading_images_to_cache", + "value": "Preloading images to file cache" + }, + { + "name": "Retrieve_image_display_from_cache", + "value": "Retrieve image display from cache" + }, + { + "name": "Test_single_request_header", + "value": "Test a single request header" + }, + { + "name": "Test_write_cache_strategy", + "value": "Test write cache strategy" + }, + { + "name": "Image_Transformation", + "value": "Image Transformation" + }, + { + "name": "Different_ObjectFit", + "value": "Different ObjectFit" + }, + { + "name": "Test_image_loading_success_or_failure_events", + "value": "Test image loading success/failure events" + }, + { + "name": "Test_removing_image_cache_interface", + "value": "Test removing image cache interface" + }, + { + "name": "Test_error_image_display", + "value": "Test error image display" + }, + { + "name": "Test_media_URL", + "value": "Test media URL" + }, + { + "name": "Display_the_first_frame", + "value": "Display the first frame of the animation" + }, + { + "name": "Display_the_last_frame", + "value": "Display the last frame of the animation" + }, + { + "name": "Play", + "value": "Play" + }, + { + "name": "Pause", + "value": "Pause" + }, + { + "name": "Stop", + "value": "Stop" + }, + { + "name": "Infinite_loop", + "value": "Infinite loop" + }, + { + "name": "Play_once", + "value": "Play once" + }, + { + "name": "Play_twice", + "value": "Play twice" + }, + { + "name": "Local_SVG", + "value": "Local SVG image" + }, + { + "name": "Under_context_file", + "value": "Files under context file" + }, + { + "name": "Network_images", + "value": "Network images" + }, + { + "name": "Custom_network_download", + "value": "Custom network download" + }, + { + "name": "PixelMap_loads_images", + "value": "PixelMap loads images" + }, + { + "name": "Enlarge", + "value": "Enlarge" + }, + { + "name": "Reduce", + "value": "Reduce" + }, + { + "name": "Click_on_add", + "value": "Click on the size to add 50" + }, + { + "name": "Click_on_reduce", + "value": "Click to reduce size by 50" + }, + { + "name": "The_key_fixed_1", + "value": "The key is fixed at 1" + }, + { + "name": "The_key_changes_timestamp", + "value": "Key changes every time: timestamp" + }, + { + "name": "Load", + "value": "Load" + }, + { + "name": "Preloading_images_to_file_cache_using_URL", + "value": "Preloading images to file cache using URL" + }, + { + "name": "Preloading_images_to_file_cache_using_option", + "value": "Preloading images to file cache using option" + }, + { + "name": "Load_image_offline_after_preloading", + "value": "Load image (can be loaded offline after preloading)" + }, + { + "name": "Preloading_GIF", + "value": "Preloading GIF" + }, + { + "name": "Retrieve_GIF_from_memory", + "value": "Retrieve GIF from memory cache" + }, + { + "name": "Retrieve_GIF_from_disk", + "value": "Retrieve GIF from disk cache" + }, + { + "name": "Preloading_static_images", + "value": "Preloading static images" + }, + { + "name": "Retrieve_images_from_memory", + "value": "Retrieve images from memory cache" + }, + { + "name": "Retrieve_images_from_disk", + "value": "Retrieve images from memory disk" + }, + { + "name": "Write_memory_and_file", + "value": "Write to memory and file cache" + }, + { + "name": "Write_memory", + "value": "Write to memory cache" + }, + { + "name": "Write_file", + "value": "Write to file cache" + }, + { + "name": "Main_image_Fill", + "value": "Main image Fill Stretch Fill" + }, + { + "name": "Maintain_proportion_filling", + "value": "Maintain proportion filling in the placeholder map 'Include'" + }, + { + "name": "Error_graph_None", + "value": "Error graph None remains unchanged" + }, + { + "name": "Test_failure_success", + "value": "Test failure/success" + }, + { + "name": "Custom_download_failed", + "value": "Custom download failed" + }, + { + "name": "Retrieve_media_gallery", + "value": "Retrieve the URI of the media gallery and display it using ImageKnife" + }, + { + "name": "Click_load_Uri", + "value": "Click to load Uri and display" + }, + { + "name": "Delete_all_caches", + "value": "Delete all caches" + }, + { + "name": "Delete_all_memory_caches", + "value": "Delete all memory caches" + }, + { + "name": "Delete_all_file_caches", + "value": "Delete all file caches" + }, + { + "name": "Delete_all_custom_memory_caches", + "value": "Delete all custom memory caches" + }, + { + "name": "Delete_all_custom_file_caches", + "value": "Delete all custom file caches" + }, + { + "name": "Blur_effect", + "value": "Blur effect" + }, + { + "name": "Highlighting_effect", + "value": "Highlighting effect" + }, + { + "name": "Ashing_effect", + "value": "Ashing effect" + }, + { + "name": "Inverse_effect", + "value": "Inverse effect" + }, + { + "name": "Animation_filter_effect", + "value": "Animation filter effect" + }, + { + "name": "Crop_circular_effect", + "value": "Crop circular effect" + }, + { + "name": "Crop_circular_with_border_effect", + "value": "Crop circular with border effect" + }, + { + "name": "Contrast_effect", + "value": "Contrast effect" + }, + { + "name": "Black_ink_filtering_effect", + "value": "Black ink filtering effect" + }, + { + "name": "Rotate", + "value": "Rotate" + }, + { + "name": "Corners", + "value": "Corners" + }, + { + "name": "Kuwahara_Filter_effect", + "value": "Kuwahara filter effect" + }, + { + "name": "Pixelated_Filter_effect", + "value": "Pixelated filtering effect" + }, + { + "name": "Sketch_Filter_effect", + "value": "Sketch Filter effect" + }, + { + "name": "Distortion_Filter_effect", + "value": "Distortion Filter effect" + }, + { + "name": "Decorative_Filter_effect", + "value": "Decorative Filter effect" + }, + { + "name": "Square_cutting_effect", + "value": "Square cutting effect" + }, + { + "name": "Top_cutting_effect", + "value": "Top cutting effect" + }, + { + "name": "Middle_cutting_effect", + "value": "Middle cutting effect" + }, + { + "name": "Bottom_cutting_effect", + "value": "Bottom cutting effect" + }, + { + "name": "Mask_effect", + "value": "Mask effect" + }, + { + "name": "TIPS", + "value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally" + }, + { + "name": "Network_reload", + "value": "Network recovery reload" + }, + { + "name": "preloading_prefetch", + "value": "Dynamic preloading prefetch" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/zh_CN/element/string.json b/entry/src/main/resources/zh_CN/element/string.json index 74fedfe..916736c 100644 --- a/entry/src/main/resources/zh_CN/element/string.json +++ b/entry/src/main/resources/zh_CN/element/string.json @@ -363,6 +363,14 @@ { "name": "TIPS", "value": "测试失败场景请先关闭网络,并保证本地没有此网络图片的缓存" + }, + { + "name": "Network_reload", + "value": "网络恢复reload" + }, + { + "name": "preloading_prefetch", + "value": "动态预加载prefetch" } ] } \ No newline at end of file diff --git a/library/oh-package.json5 b/library/oh-package.json5 index ca33846..2cac89f 100644 --- a/library/oh-package.json5 +++ b/library/oh-package.json5 @@ -14,7 +14,7 @@ "main": "index.ets", "repository": "https://gitee.com/openharmony-tpc/ImageKnife", "type": "module", - "version": "3.1.1-rc.0", + "version": "3.1.1-rc.1", "dependencies": { "@ohos/gpu_transform": "^1.0.2" }, diff --git a/library/src/main/ets/ImageKnife.ets b/library/src/main/ets/ImageKnife.ets index 41eeb64..879055b 100644 --- a/library/src/main/ets/ImageKnife.ets +++ b/library/src/main/ets/ImageKnife.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ImageKnifeRequest } from './model/ImageKnifeRequest'; +import { ImageKnifeRequest, ImageKnifeRequestState } from './model/ImageKnifeRequest'; import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData'; import { MemoryLruCache } from './cache/MemoryLruCache'; import { IMemoryCache } from './cache/IMemoryCache' @@ -137,7 +137,48 @@ export class ImageKnife { let key = this.getEngineKeyImpl().generateMemoryKey(imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC, imageKnifeOption); this.memoryCache.remove(key); } - + /** + * 重新加载 + */ + reload(request: ImageKnifeRequest) { + if (request.requestState == ImageKnifeRequestState.ERROR) { + request.requestState = ImageKnifeRequestState.PROGRESS + ImageKnife.getInstance().execute(request) + } + } + /** + * 预加载 + * @param loadSrc 图片地址url + * @returns 图片请求request + */ + preload(loadSrc:string | ImageKnifeOption):ImageKnifeRequest{ + let imageKnifeOption = new ImageKnifeOption() + if (typeof loadSrc == "string") { + imageKnifeOption.loadSrc = loadSrc + } else { + imageKnifeOption = loadSrc; + } + let request = new ImageKnifeRequest( + imageKnifeOption, + imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext(this) as common.UIAbilityContext, + 0, + 0, + 0, + { + showPixelMap(version: number, pixelMap: PixelMap | string) { + } + } + ) + this.execute(request) + return request + } + /** + * 取消图片请求 + * @param request 图片请求request + */ + cancel(request:ImageKnifeRequest) { + request.requestState = ImageKnifeRequestState.DESTROY + } /** * 预加载图片到文件缓存 @@ -384,10 +425,10 @@ export class ImageKnife { * 全局设置自定义下载 * @param customGetImage 自定义请求函数 */ - setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise) { + setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise) { this.customGetImage = customGetImage } - getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource) => Promise){ + getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise){ return this.customGetImage } } \ No newline at end of file diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index fbbb3a8..e99d621 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -260,7 +260,7 @@ export class ImageKnifeDispatcher { if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined && requestJobResult.loadFail) { - requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail); + requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request); LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc) } if (requestWithSource.source === ImageKnifeRequestSource.SRC && diff --git a/library/src/main/ets/ImageKnifeLoader.ets b/library/src/main/ets/ImageKnifeLoader.ets index 1c14d0c..dd8e1bf 100644 --- a/library/src/main/ets/ImageKnifeLoader.ets +++ b/library/src/main/ets/ImageKnifeLoader.ets @@ -193,7 +193,20 @@ export class ImageKnifeLoader { return ImageKnifeLoader.makeEmptyResult("ImageKnifeAnimatorComponent组件仅支持动态图") } } - + // 获取请求头 + static getHeaderObj(request:RequestJobRequest){ + const headerObj: Record = {} + if (request.headers != undefined) { + request.headers.forEach((value) => { + headerObj[value.key] = value.value + }) + } else if (request.allHeaders.size > 0) { + request.allHeaders.forEach((value, key) => { + headerObj[key] = value + }) + } + return headerObj + } // 获取图片资源 static async getImageArrayBuffer(request: RequestJobRequest, requestList: List | undefined,fileKey:string): Promise { let resBuf: ArrayBuffer | undefined @@ -205,7 +218,8 @@ export class ImageKnifeLoader { if (resBuf === undefined) { LogUtil.log("start customGetImage src=" + request.src) try { - resBuf = await request.customGetImage(request.context, request.src) + const headerObj: Record = ImageKnifeLoader.getHeaderObj(request) + resBuf = await request.customGetImage(request.context, request.src,headerObj) LogUtil.log("end customGetImage src=" + request.src) } catch (err) { throw new Error('customGetImage loadFile failed! err = ' + err) @@ -234,16 +248,7 @@ export class ImageKnifeLoader { let httpRequest = http.createHttp(); let progress: number = 0 let arrayBuffers = new Array() - const headerObj: Record = {} - if (request.headers != undefined) { - request.headers.forEach((value) => { - headerObj[value.key] = value.value - }) - } else if (request.allHeaders.size > 0) { - request.allHeaders.forEach((value, key) => { - headerObj[key] = value - }) - } + const headerObj: Record = ImageKnifeLoader.getHeaderObj(request) httpRequest.on("dataReceive", (data: ArrayBuffer) => { arrayBuffers.push(data) }); diff --git a/library/src/main/ets/model/ImageKnifeData.ets b/library/src/main/ets/model/ImageKnifeData.ets index e8a4c2a..153ebdd 100644 --- a/library/src/main/ets/model/ImageKnifeData.ets +++ b/library/src/main/ets/model/ImageKnifeData.ets @@ -91,7 +91,7 @@ export interface RequestJobRequest { allHeaders: Map, componentWidth: number, componentHeight: number, - customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise, + customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise, onlyRetrieveFromCache?: boolean requestSource: ImageKnifeRequestSource transformation?: PixelMapTransformation diff --git a/library/src/main/ets/model/ImageKnifeOption.ets b/library/src/main/ets/model/ImageKnifeOption.ets index 5c5f292..9e6285b 100644 --- a/library/src/main/ets/model/ImageKnifeOption.ets +++ b/library/src/main/ets/model/ImageKnifeOption.ets @@ -17,6 +17,7 @@ import common from '@ohos.app.ability.common' import { CacheStrategy, ImageKnifeData,EventImage } from './ImageKnifeData'; import { PixelMapTransformation } from '../transform/PixelMapTransformation'; import { drawing } from '@kit.ArkGraphics2D'; +import { ImageKnifeRequest } from './ImageKnifeRequest'; export interface HeaderOptions { key: string; @@ -77,7 +78,7 @@ interface ImageOption { placeholderObjectFit?: ImageFit // 错误图填充效果 errorholderObjectFit?: ImageFit - customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise + customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record) => Promise border?: BorderOptions // 缓存策略 writeCacheStrategy?: CacheStrategy @@ -155,7 +156,7 @@ export interface OnLoadCallBack { onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData) => void; // 请求结束 - onLoadFailed?: (err: string) => void; + onLoadFailed?: (err: string,request?: ImageKnifeRequest) => void; // 请求取消 onLoadCancel?: (reason: string) => void; } \ No newline at end of file