From aa2cd9c1bf6791356eff4ccb2d0fa9c02ea1151f Mon Sep 17 00:00:00 2001 From: zgf Date: Wed, 9 Oct 2024 11:13:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ereload=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=92=8C=E7=BD=91=E7=BB=9C=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E5=8A=A0=E8=BD=BD=E6=A0=B7=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zgf --- README_zh.md | 29 ++++--- entry/src/main/ets/pages/ImageKnifeReload.ets | 82 ++++++++++++++++++ entry/src/main/ets/pages/Index.ets | 5 ++ entry/src/main/module.json5 | 9 ++ .../resources/base/profile/main_pages.json | 3 +- library/src/main/ets/ImageKnife.ets | 12 ++- library/src/main/ets/ImageKnifeDispatcher.ets | 2 +- .../src/main/ets/model/ImageKnifeOption.ets | 3 +- .../src/main/resources/base/media/rabbit.gif | Bin 10208 -> 0 bytes 9 files changed, 126 insertions(+), 19 deletions(-) create mode 100644 entry/src/main/ets/pages/ImageKnifeReload.ets delete mode 100644 library/src/main/resources/base/media/rabbit.gif diff --git a/README_zh.md b/README_zh.md index 97522da..698a31a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -311,20 +311,21 @@ ImageKnifeAnimatorComponent({ ### ImageKnife接口 -| 参数名称 | 入参内容 | 功能简介 | -|------------------|-------------------------------------------------------------------------------------------------------|---------------| -| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 | -| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | -| 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 | 全局设置自定义下载 | -| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | -| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | -| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 | -| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 | +| 参数名称 | 入参内容 | 功能简介 | +|-------------------|-------------------------------------------------------------------------------------------------------|------------------| +| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 | +| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | +| reload | 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 | 全局设置自定义下载 | +| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | +| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | +| 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..938f1ce --- /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 } from '@ohos/libraryimageknife' + +@Entry +@Component +struct ImageKnifeReload { + aboutToAppear(): void { + NetWatchState.init() + } + build() { + Column() { + ImageKnifeComponent({ + 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:{ + 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 329e33a..209d789 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -35,6 +35,11 @@ struct Index { uri: 'pages/ImageAnimatorPage', }); }) + Button("网络恢复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/module.json5 b/entry/src/main/module.json5 index 9036eb0..d180623 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -43,6 +43,15 @@ ], "when": "always" } + }, + { + "name": "ohos.permission.GET_NETWORK_INFO", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "always" + } } ] } diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index de593dd..c8098d3 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -23,6 +23,7 @@ "pages/ImageAnimatorPage", "pages/TestSetCustomImagePage", "pages/TestErrorHolderPage", - "pages/TestTaskResourcePage" + "pages/TestTaskResourcePage", + "pages/ImageKnifeReload" ] } \ No newline at end of file diff --git a/library/src/main/ets/ImageKnife.ets b/library/src/main/ets/ImageKnife.ets index 69a6271..b36fad1 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' @@ -80,7 +80,15 @@ export class ImageKnife { public isFileCacheInit(): boolean { return this.fileCache === undefined ? false : this.fileCache.isFileCacheInit() } - + /** + * 重新加载 + */ + reload(request: ImageKnifeRequest) { + if (request.requestState == ImageKnifeRequestState.ERROR) { + request.requestState = ImageKnifeRequestState.PROGRESS + ImageKnife.getInstance().execute(request) + } + } /** * 全局添加单个请求头header * @param key 请求头属性 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/model/ImageKnifeOption.ets b/library/src/main/ets/model/ImageKnifeOption.ets index 974b53b..ed70f48 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; @@ -89,7 +90,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 diff --git a/library/src/main/resources/base/media/rabbit.gif b/library/src/main/resources/base/media/rabbit.gif deleted file mode 100644 index c2c1402e563c2d86c957b8d37ab28283b5b95986..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10208 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 W3^IJOG6Lo@f*CTMgrER`^#23sTkf9#