commit
668bf251fd
|
@ -3,6 +3,7 @@
|
|||
- 提供图片加载成功/失败的事件
|
||||
- 修复懒加载在多次点击出现卡死的问题
|
||||
- 支持多种组合变换
|
||||
- 提供清理缓存能力
|
||||
|
||||
## 2.2.0-rc.2
|
||||
- ImageKnife支持下采样
|
||||
|
|
|
@ -381,6 +381,12 @@ request.skipMemoryCache(true)
|
|||
| resumeRequests() | | 全局恢复暂停 |
|
||||
| isUrlExist(url, cacheType, size) | url, CacheType, Size | 判断图片是否在 缓存和磁盘中存在,如果入参是缓存,需要传入值图片大小,参数 CacheType, Size(可选) |
|
||||
| setMaxRequests(count: number) | count | 设置请求的最大并发数量 |
|
||||
| removeAllMemoryCache() | | 清除全部内存缓存 |
|
||||
| removeAllFileCache() | | 清除全部磁盘缓存 |
|
||||
| removeMemoryCache(url: string) | url: string | 清除指定内存缓存 |
|
||||
| removeFileCache(url: string) | url: string | 清除指定磁盘缓存 |
|
||||
| getMemoryCacheKey(url: string) | url: string | 获取指定图片内存缓存key |
|
||||
| getDiskCacheKey(url: string) | url: string | 获取指定图片磁盘缓存key |
|
||||
|
||||
### 缓存策略相关
|
||||
|
||||
|
|
|
@ -438,6 +438,14 @@ struct IndexFunctionDemo {
|
|||
router.pushUrl({ url: 'pages/testImageKnifeLoadState' });
|
||||
}).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/testImageKnifeRemoveCache' });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
}.width('100%').height(60).backgroundColor(Color.Pink)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* 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,
|
||||
ImageKnifeGlobal,
|
||||
ImageKnife,
|
||||
ImageKnifeData,
|
||||
Size,
|
||||
CacheType
|
||||
} from '@ohos/libraryimageknife'
|
||||
import image from '@ohos.multimedia.image';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
|
||||
let imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeRemoveCache {
|
||||
@State url: string = '';
|
||||
@State urlGif: string = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658';
|
||||
@State urlPng: string = 'https://img-blog.csdnimg.cn/20191215043500229.png';
|
||||
@State urlJpg: string = 'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB';
|
||||
@State urlBmp: string = 'https://img-blog.csdn.net/20140514114029140';
|
||||
@State urlWebp: string = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
||||
@State imagePixelMap: PixelMap | undefined = undefined;
|
||||
@State imagePixelMap_: PixelMap | undefined = undefined;
|
||||
private index_: number = -1;
|
||||
private tempSize: number = 200;
|
||||
private timeId = -1;
|
||||
private comSize: Size = {
|
||||
width: this.tempSize,
|
||||
height: this.tempSize,
|
||||
}
|
||||
@State imageKnifeOption: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
};
|
||||
loadSuccess = (data: ImageKnifeData) => {
|
||||
clearTimeout(this.timeId);
|
||||
if (data.isPixelMap()) {
|
||||
if (data.drawPixelMap) {
|
||||
let pixelmap = data.drawPixelMap.imagePixelMap;
|
||||
if (pixelmap) {
|
||||
if (this.index_ == 1) {
|
||||
this.imagePixelMap = pixelmap;
|
||||
} else if (this.index_ == 2) {
|
||||
this.imagePixelMap_ = pixelmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.isGIFFrame()) {
|
||||
let index: number = 0
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let renderGif = () => {
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let pixelmap = data.drawGIFFrame.imageGIFFrames[index].drawPixelMap;
|
||||
let delay = data.drawGIFFrame.imageGIFFrames[index].delay;
|
||||
if (pixelmap) {
|
||||
if (this.index_ == 1) {
|
||||
this.imagePixelMap = pixelmap;
|
||||
} else if (this.index_ == 2) {
|
||||
this.imagePixelMap_ = pixelmap;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
if (index == data.drawGIFFrame.imageGIFFrames.length - 1) {
|
||||
index = 0;
|
||||
}
|
||||
this.timeId = setTimeout(renderGif, data!.drawGIFFrame!.imageGIFFrames![index].delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
renderGif();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loadError = (err: BusinessError) => {
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
|
||||
Text('图片内存和磁盘缓存删除').fontSize(30);
|
||||
Text('测试删除缓存时候关闭掉网络').fontSize(15);
|
||||
|
||||
Row() {
|
||||
Button('png')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlPng;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('bmp')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlBmp;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('webp')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlWebp;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('jpg')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlJpg;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('gif')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlGif;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Row() {
|
||||
Button('缓存图片')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 1;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Cache, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
|
||||
Button('磁盘图片')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 2;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Disk, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Row() {
|
||||
Button('清除全部缓存')
|
||||
.onClick(() => {
|
||||
imageKnife?.removeAllMemoryCache();
|
||||
imageKnife?.removeAllFileCache();
|
||||
})
|
||||
|
||||
Button('清除全部内存缓存')
|
||||
.onClick(() => {
|
||||
imageKnife?.removeAllMemoryCache();
|
||||
})
|
||||
|
||||
Button('清除全部磁盘缓存')
|
||||
.onClick(() => {
|
||||
imageKnife?.removeAllFileCache();
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Row() {
|
||||
Button('清除指定内存缓存')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
imageKnife?.removeMemoryCache(this.url);
|
||||
})
|
||||
|
||||
Button('清除指定磁盘缓存')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
imageKnife?.removeFileCache(this.url);
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Text('网络图').fontSize(15);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
Text('缓存图').fontSize(15);
|
||||
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.imagePixelMap as image.PixelMap
|
||||
}
|
||||
})
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
Text('磁盘图').fontSize(15);
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.imagePixelMap_ as image.PixelMap
|
||||
}
|
||||
})
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
}
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width('100%')
|
||||
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
|
||||
}
|
||||
|
||||
aboutToDisappear() {
|
||||
|
||||
}
|
||||
|
||||
onBackPress() {
|
||||
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@
|
|||
"pages/testCustomDataFetchClientWithPage",
|
||||
"pages/testReuseAblePages",
|
||||
"pages/downsamplingPage",
|
||||
"pages/testImageKnifeLoadState"
|
||||
"pages/testImageKnifeLoadState",
|
||||
"pages/testImageKnifeRemoveCache"
|
||||
]
|
||||
}
|
|
@ -14,7 +14,9 @@
|
|||
*/
|
||||
import hilog from '@ohos.hilog';
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
|
||||
import {ImageKnife,ImageKnifeDrawFactory,ImageKnifeGlobal} from '@ohos/imageknife'
|
||||
import { DiskLruCache, ImageKnife,ImageKnifeDrawFactory,ImageKnifeGlobal,LruCache} from '@ohos/imageknife';
|
||||
import { common } from '@kit.AbilityKit';
|
||||
import { GlobalContext } from '../testability/GlobalContext';
|
||||
|
||||
const BASE_COUNT: number = 2000;
|
||||
|
||||
|
@ -74,6 +76,33 @@ export default function ImageKnifeTest() {
|
|||
}
|
||||
|
||||
})
|
||||
it('TestRemoveAllMemoryCache',2,()=>{
|
||||
let imageKnife:ImageKnife|undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
imageKnife?.removeAllMemoryCache();
|
||||
let a = imageKnife?.getMemoryCache();
|
||||
expect(a).assertEqual(undefined);
|
||||
})
|
||||
it('TestRemoveAllFileCache',3,()=>{
|
||||
let imageKnife:ImageKnife|undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
imageKnife?.removeAllFileCache();
|
||||
let a = imageKnife?.getDiskMemoryCache();
|
||||
expect(a).assertEqual(undefined);
|
||||
})
|
||||
it('TestRemoveMemoryCache',4,()=>{
|
||||
let memoryCache = new LruCache<string, string>(5);
|
||||
memoryCache.put("1","1");
|
||||
memoryCache.remove("1");
|
||||
let result = memoryCache.get("1");
|
||||
expect(result).assertEqual(undefined);
|
||||
})
|
||||
it('TestRemoveFileCache',5,()=>{
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let disLruCache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
disLruCache.set('test', "Hello World Simple Example.");
|
||||
disLruCache.deleteCacheDataByKey('test');
|
||||
let a = disLruCache.get('test');
|
||||
expect(a).assertEqual(undefined);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -272,6 +272,14 @@ export class DiskLruCache {
|
|||
this.cacheMap.clear()
|
||||
this.size = 0
|
||||
}
|
||||
async cleanAllDiskCache() {
|
||||
let filenames: string[] = await FileUtils.getInstance().ListFile(this.path);
|
||||
for (let i = 0; i < filenames.length; i++) {
|
||||
await FileUtils.getInstance().deleteFile(this.path + filenames[i]);
|
||||
}
|
||||
this.cacheMap.clear();
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
getCacheMap() {
|
||||
return this.cacheMap;
|
||||
|
|
|
@ -410,5 +410,13 @@ export class FileUtils {
|
|||
fs.readSync(fd, buf)
|
||||
return buf
|
||||
}
|
||||
async ListFile(path: string): Promise<string[]> {
|
||||
try {
|
||||
return fs.listFile(path);
|
||||
} catch (err) {
|
||||
console.error("FileUtils ListFile failed with error message: " + err.message + ", error code: " + err.code);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,13 @@ export class LruCache<K, V> {
|
|||
}
|
||||
return preValue
|
||||
}
|
||||
removeAll() {
|
||||
this.map.each((value, key) => {
|
||||
this.remove(key);
|
||||
})
|
||||
this.map.clear();
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
// 获取键为key的value
|
||||
get(key: K): V | undefined {
|
||||
|
|
|
@ -171,6 +171,66 @@ export class ImageKnife {
|
|||
setMemoryCache(lrucache: MemoryLruCache) {
|
||||
this.memoryCache = lrucache;
|
||||
}
|
||||
// 移除全部内存缓存
|
||||
removeAllMemoryCache(): void {
|
||||
this.memoryCacheProxy.removeAllValue();
|
||||
}
|
||||
// 移除全部磁盘缓存
|
||||
async removeAllFileCache(): Promise<void> {
|
||||
if (this.diskMemoryCache !== undefined) {
|
||||
await this.getDiskMemoryCache().cleanAllDiskCache();
|
||||
}
|
||||
}
|
||||
// 移除指定内存缓存
|
||||
removeMemoryCache(url: string): void {
|
||||
let key = this.getMemoryCacheKey(url);
|
||||
this.memoryCacheProxy.removeValue(key);
|
||||
}
|
||||
// 移除指定磁盘缓存
|
||||
removeFileCache(url: string): void {
|
||||
let key = this.getDiskCacheKey(url);
|
||||
this.diskMemoryCache.deleteCacheDataByKey(key);
|
||||
}
|
||||
// 获取指定内存缓存key值
|
||||
getMemoryCacheKey(url: string) {
|
||||
let request = new RequestOption();
|
||||
let factories: EngineKeyInterface;
|
||||
let dontAnimateFlag = request.dontAnimateFlag;
|
||||
let signature = request.signature;
|
||||
const imageSize: Size = {
|
||||
width: 200,
|
||||
height: 200,
|
||||
}
|
||||
let size = JSON.stringify(imageSize);
|
||||
if (this.engineKeyImpl) {
|
||||
factories = this.engineKeyImpl;
|
||||
} else {
|
||||
factories = new EngineKeyFactories();
|
||||
}
|
||||
let transformed = '';
|
||||
if (request && request.transformations) {
|
||||
for (let i = 0; i < request.transformations.length; i++) {
|
||||
if (i == request.transformations.length - 1) {
|
||||
transformed += request.transformations[i].getName() + "";
|
||||
} else {
|
||||
transformed += request.transformations[i].getName() + ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
return factories.generateMemoryCacheKey(url, size, transformed, dontAnimateFlag, signature);
|
||||
}
|
||||
// 获取指定磁盘缓存key值
|
||||
getDiskCacheKey(url: string) {
|
||||
let request = new RequestOption();
|
||||
let signature = request.signature;
|
||||
let factories: EngineKeyInterface;
|
||||
if (this.engineKeyImpl) {
|
||||
factories = this.engineKeyImpl;
|
||||
} else {
|
||||
factories = new EngineKeyFactories();
|
||||
}
|
||||
return factories.generateOriginalDiskCacheKey(url, signature);
|
||||
}
|
||||
|
||||
getDefaultListener() {
|
||||
return this.defaultListener;
|
||||
|
|
|
@ -39,6 +39,9 @@ export class MemoryCacheProxy <K, V> implements ICache<K, V> {
|
|||
removeValue(key: K): V|undefined{
|
||||
return this.mLruCache.remove(key);
|
||||
}
|
||||
removeAllValue() {
|
||||
this.mLruCache.removeAll();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.mLruCache.evicAll();
|
||||
|
|
Loading…
Reference in New Issue