ImageKnife/library/src/main/ets/utils/MemoryLruCache.ets

137 lines
4.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 { ImageKnifeData } from '../model/ImageKnifeData';
import util from '@ohos.util';
import { IMemoryCache } from './IMemoryCache';
export class MemoryLruCache implements IMemoryCache {
maxMemory: number = 0
currentMemory: number = 0
maxSize: number = 0
private lruCache: util.LRUCache<string, ImageKnifeData>
readonly defaultMaxSize: number = 4096
readonly defaultSize: number = 512
readonly defaultMaxMemorySize: number = 1024 * 1024 * 1024
readonly defaultMemorySize: number = 128 * 1024 * 1024
constructor(size: number, memory: number) {
if (size <= 0 || size > this.defaultMaxSize) {
size = this.defaultSize
}
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
memory = this.defaultMemorySize
}
this.lruCache = new util.LRUCache(size);
this.maxMemory = memory
this.maxSize = size
this.currentMemory = 0
}
// 添加缓存键值对
put(key: string, value: ImageKnifeData): void {
if (key == null || value == null) {
throw new Error('key or value is invalid ');
}
// 如果size满了的话需要按照LRU的方式删除第一个
if (this.lruCache.length == this.maxSize && !this.lruCache.contains(key)) {
this.remove(this.lruCache.keys()[0])
} else if (this.lruCache.contains(key)) {
this.remove(key)
}
let pre: ImageKnifeData = this.lruCache.put(key, value)
this.addMemorySize(value)
// if (pre !== undefined) { // 当前返回不是key的之前value
// this.removeMemorySize(pre)
// }
this.trimToSize();
}
get(key: string): ImageKnifeData | undefined {
return this.lruCache.get(key)
}
// 移除键为key的缓存
remove(key: string): ImageKnifeData | undefined {
if (key == null) {
throw new Error('key is null,checking the parameter');
}
let remove: ImageKnifeData | undefined = this.lruCache.remove(key)
if (remove !== undefined) {
this.removeMemorySize(remove)
}
return remove
}
removeAll(): void {
this.lruCache.clear()
this.currentMemory = 0;
}
size(): number {
return this.lruCache.length
}
// 移除较少使用的缓存数据
trimToSize(): void {
while (true) {
if (this.currentMemory <= this.maxMemory || this.lruCache.isEmpty()) {
break
}
let delkey = this.lruCache.keys()[0]
let data: ImageKnifeData | undefined = this.lruCache.get(delkey)
if (data != undefined) {
this.removeMemorySize(data)
}
this.lruCache.remove(delkey)
}
}
private removeMemorySize(value: ImageKnifeData): void {
if (value.source != undefined) {
if (typeof value.source === 'string' && value.source != "") {
this.currentMemory -= value.source.length
} else if (value.source == "") {
for (let index = 0;index < value.imageAnimator!.length;index++) {
let pixelMap = value.imageAnimator![index].src as PixelMap
this.currentMemory -= pixelMap.getPixelBytesNumber()
}
} else {
this.currentMemory -= value.source.getPixelBytesNumber();
value.source.release()
}
// LogUtil.info("MemoryCache removeMemorySize: " + value.source.getPixelBytesNumber() + " currentMemory" + this.currentMemory)
}
}
private addMemorySize(value: ImageKnifeData): void {
if (value.source != undefined) {
if (typeof value.source === 'string' && value.source != "") {
this.currentMemory += value.source.length
} else if (value.source == "") {
for (let index = 0;index < value.imageAnimator!.length;index++) {
let pixelMap = value.imageAnimator![index].src as PixelMap
this.currentMemory += pixelMap.getPixelBytesNumber()
}
} else {
this.currentMemory += value.source.getPixelBytesNumber();
}
//LogUtil.log("MemoryCache addMemorySize: " + value.source.getPixelBytesNumber() + " currentMemory" + this.currentMemory)
}
}
}