forked from floraachy/ImageKnife
137 lines
4.5 KiB
Plaintext
137 lines
4.5 KiB
Plaintext
/*
|
||
* 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)
|
||
}
|
||
}
|
||
} |