1.修改memorykey生成
2.文件缓存key由子线程生成,返回到主线程管理 Signed-off-by: madixin <madixin@huawei.com>
This commit is contained in:
parent
33ba458600
commit
91634663dc
30
README.md
30
README.md
|
@ -138,22 +138,22 @@ ImageKnifeComponent({ ImageKnifeOption:
|
||||||
## 接口说明
|
## 接口说明
|
||||||
### ImageKnifeOption参数列表
|
### ImageKnifeOption参数列表
|
||||||
|
|
||||||
| 参数名称 | 入参内容 | 功能简介 |
|
| 参数名称 | 入参内容 | 功能简介 |
|
||||||
|-----------------------|-------------------------------|-----------------|
|
|-----------------------|--------------------------------|-----------------|
|
||||||
| loadSrc | string、PixelMap、Resource | 主图展示 |
|
| loadSrc | string、PixelMap、Resource | 主图展示 |
|
||||||
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
|
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
|
||||||
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
|
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
|
||||||
| objectFit | ImageFit | 图片展示样式(可选) |
|
| objectFit | ImageFit | 图片展示样式(可选) |
|
||||||
| writeCacheStrategy | WriteCacheStrategyType | 写入缓存策略(可选) |
|
| writeCacheStrategy | WriteCacheStrategyType | 写入缓存策略(可选) |
|
||||||
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
|
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
|
||||||
| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
|
| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
|
||||||
| border | BorderOptions | 边框圆角(可选) |
|
| border | BorderOptions | 边框圆角(可选) |
|
||||||
| priority | taskpool.Priority | 加载优先级(可选) |
|
| priority | taskpool.Priority | 加载优先级(可选) |
|
||||||
| context | common.UIAbilityContext | 上下文(可选) |
|
| context | common.UIAbilityContext | 上下文(可选) |
|
||||||
| progressListener | (progress: number)=>void | 进度(可选) |
|
| progressListener | (progress: number)=>void | 进度(可选) |
|
||||||
| signature | ObjectKey | 自定义缓存关键字(可选) |
|
| signature | String | 自定义缓存关键字(可选) |
|
||||||
| headerOption | Array<HeaderOptions> | 设置请求头(可选) |
|
| headerOption | Array<HeaderOptions> | 设置请求头(可选) |
|
||||||
| transformation | PixelMapTransformation | 图片变换(可选) |
|
| transformation | PixelMapTransformation | 图片变换(可选) |
|
||||||
|
|
||||||
### ImageKnife接口
|
### ImageKnife接口
|
||||||
| 参数名称 | 入参内容 | 功能简介 |
|
| 参数名称 | 入参内容 | 功能简介 |
|
||||||
|
|
|
@ -12,46 +12,35 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import util from '@ohos.util';
|
import { IEngineKey, ImageKnifeOption, PixelMapTransformation } from '@ohos/imageknife';
|
||||||
import { IEngineKey, ImageKnifeOption, ObjectKey , PixelMapTransformation } from '@ohos/imageknife';
|
|
||||||
import { SparkMD5 } from '@ohos/imageknife/src/main/ets/3rd_party/sparkmd5/spark-md5';
|
import { SparkMD5 } from '@ohos/imageknife/src/main/ets/3rd_party/sparkmd5/spark-md5';
|
||||||
|
import { ImageKnifeRequestSource } from '@ohos/imageknife/src/main/ets/ImageKnifeDispatcher';
|
||||||
|
|
||||||
//全局自定义key demo
|
//全局自定义key demo
|
||||||
|
@Sendable
|
||||||
export class CustomEngineKeyImpl implements IEngineKey {
|
export class CustomEngineKeyImpl implements IEngineKey {
|
||||||
private memoryKeyCache: util.LRUCache<string, string> = new util.LRUCache(1024)
|
|
||||||
private fileKeyCache: util.LRUCache<string, string> = new util.LRUCache(1024)
|
|
||||||
|
|
||||||
// 生成内存缓存key
|
// 生成内存缓存key
|
||||||
generateMemoryKey(loadSrc: string | PixelMap | Resource, imageKnifeOption: ImageKnifeOption): string {
|
generateMemoryKey(loadSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,
|
||||||
let src = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
imageKnifeOption: ImageKnifeOption, width?: number, height?: number): string {
|
||||||
if (imageKnifeOption.signature) {
|
let key = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
||||||
src += "signature=" + imageKnifeOption.signature.getKey() + ";"
|
if (requestSource === ImageKnifeRequestSource.SRC) {
|
||||||
|
if (imageKnifeOption.signature !== undefined && imageKnifeOption.signature !== "") {
|
||||||
|
key += "signature=" + imageKnifeOption.signature + ";"
|
||||||
|
}
|
||||||
|
if (imageKnifeOption.transformation) {
|
||||||
|
key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (imageKnifeOption.transformation) {
|
return key
|
||||||
src += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";"
|
|
||||||
}
|
|
||||||
return this.generateKey(src, this.memoryKeyCache)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成文件缓存key
|
// 生成文件缓存key
|
||||||
generateFileKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string {
|
generateFileKey(loadSrc: string | PixelMap | Resource, signature?: string): string {
|
||||||
let src = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
let src = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
||||||
if (signature) {
|
if (signature !== undefined && signature !== "") {
|
||||||
src += "signature=" + signature.getKey() + ";"
|
src += "signature=" + signature + ";"
|
||||||
}
|
|
||||||
return this.generateKey(src, this.fileKeyCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// key缓存策略,避免无意义的 JSON.stringify
|
|
||||||
private generateKey(keyCache: string, cache: util.LRUCache<string, string>): string {
|
|
||||||
let result = cache.get(keyCache)
|
|
||||||
if (result != undefined) {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result = SparkMD5.hashBinary(keyCache)
|
|
||||||
cache.put(keyCache, result)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
return SparkMD5.hashBinary(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTransformation(transformation: PixelMapTransformation): string {
|
private getTransformation(transformation: PixelMapTransformation): string {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeComponent, ImageKnifeOption, ObjectKey } from '@ohos/imageknife';
|
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife';
|
||||||
|
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
|
@ -40,7 +40,7 @@ struct SignatureTestPage {
|
||||||
this.imageKnifeOption1 = {
|
this.imageKnifeOption1 = {
|
||||||
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
||||||
placeholderSrc:$r("app.media.loading"),
|
placeholderSrc:$r("app.media.loading"),
|
||||||
signature: new ObjectKey("1")
|
signature: "1"
|
||||||
}
|
}
|
||||||
}).margin({ top: 5, left: 3 })
|
}).margin({ top: 5, left: 3 })
|
||||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
||||||
|
@ -53,7 +53,7 @@ struct SignatureTestPage {
|
||||||
this.imageKnifeOption2 = {
|
this.imageKnifeOption2 = {
|
||||||
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
||||||
placeholderSrc:$r("app.media.loading"),
|
placeholderSrc:$r("app.media.loading"),
|
||||||
signature: new ObjectKey(new Date().getTime().toString())
|
signature: new Date().getTime().toString()
|
||||||
}
|
}
|
||||||
}).margin({ top: 5, left: 3 })
|
}).margin({ top: 5, left: 3 })
|
||||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300)
|
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300)
|
||||||
|
@ -66,7 +66,7 @@ struct SignatureTestPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToAppear() {
|
aboutToAppear() {
|
||||||
console.log("唯一标识页面:" + new ObjectKey(new Date().getTime().toString()).getKey())
|
console.log("唯一标识页面:" + new Date().getTime().toString())
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,8 +12,6 @@ export { LogUtil } from './src/main/ets/utils/LogUtil'
|
||||||
|
|
||||||
export { IEngineKey } from './src/main/ets/key/IEngineKey'
|
export { IEngineKey } from './src/main/ets/key/IEngineKey'
|
||||||
|
|
||||||
export { ObjectKey } from './src/main/ets/model/ObjectKey'
|
|
||||||
|
|
||||||
export { ImageKnifeData , ReadCacheStrategyType} from "./src/main/ets/model/ImageKnifeData"
|
export { ImageKnifeData , ReadCacheStrategyType} from "./src/main/ets/model/ImageKnifeData"
|
||||||
|
|
||||||
export { PixelMapTransformation } from './src/main/ets/transform/PixelMapTransformation'
|
export { PixelMapTransformation } from './src/main/ets/transform/PixelMapTransformation'
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { ReadCacheStrategyType, ImageKnifeData } from './model/ImageKnifeData';
|
||||||
import { MemoryLruCache } from './utils/MemoryLruCache';
|
import { MemoryLruCache } from './utils/MemoryLruCache';
|
||||||
import { IMemoryCache } from './utils/IMemoryCache'
|
import { IMemoryCache } from './utils/IMemoryCache'
|
||||||
import { FileCache } from './utils/FileCache';
|
import { FileCache } from './utils/FileCache';
|
||||||
import { ImageKnifeDispatcher } from './ImageKnifeDispatcher';
|
import { ImageKnifeDispatcher, ImageKnifeRequestSource } from './ImageKnifeDispatcher';
|
||||||
import { IEngineKey } from './key/IEngineKey';
|
import { IEngineKey } from './key/IEngineKey';
|
||||||
import { HeaderOptions, ImageKnifeOption } from './ImageKnifeOption';
|
import { HeaderOptions, ImageKnifeOption } from './ImageKnifeOption';
|
||||||
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
||||||
|
@ -120,17 +120,17 @@ export class ImageKnife {
|
||||||
return this.fileCache as FileCache
|
return this.fileCache as FileCache
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 预加载到缓存
|
* 预加载到文件缓存
|
||||||
* @param loadSrc 图片地址url
|
* @param loadSrc 图片地址url
|
||||||
* @returns 返回文件缓存路径
|
* @returns 返回文件缓存路径
|
||||||
*/
|
*/
|
||||||
preLoadCache(loadSrc:string): Promise<string> {
|
preLoadCache(loadSrc: string): Promise<string> {
|
||||||
return new Promise((resolve,reject)=>{
|
return new Promise((resolve,reject)=>{
|
||||||
let imageKnifeOption = new ImageKnifeOption()
|
let imageKnifeOption = new ImageKnifeOption()
|
||||||
imageKnifeOption.loadSrc = loadSrc
|
imageKnifeOption.loadSrc = loadSrc
|
||||||
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
|
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
|
||||||
let keys = engineKeyImpl.generateMemoryKey(loadSrc, imageKnifeOption)
|
let fileKey = engineKeyImpl.generateFileKey(loadSrc)
|
||||||
let cachePath = ImageKnife.getInstance().getFileCache().getFileToPath(keys)
|
let cachePath = ImageKnife.getInstance().getFileCache().getFileToPath(fileKey)
|
||||||
if(cachePath == null || cachePath == "" || cachePath == undefined) {
|
if(cachePath == null || cachePath == "" || cachePath == undefined) {
|
||||||
let request = new ImageKnifeRequest(
|
let request = new ImageKnifeRequest(
|
||||||
imageKnifeOption,
|
imageKnifeOption,
|
||||||
|
@ -140,7 +140,7 @@ export class ImageKnife {
|
||||||
0,
|
0,
|
||||||
{
|
{
|
||||||
showPixelMap(version: number, pixelMap: PixelMap | string) {
|
showPixelMap(version: number, pixelMap: PixelMap | string) {
|
||||||
resolve(ImageKnife.getInstance().getFileCache().getFileToPath(keys))
|
resolve(ImageKnife.getInstance().getFileCache().getFileToPath(fileKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -176,9 +176,9 @@ export class ImageKnife {
|
||||||
}
|
}
|
||||||
|
|
||||||
private readMemoryCache(loadSrc: string,option: ImageKnifeOption, engineKey: IEngineKey): ImageKnifeData | undefined {
|
private readMemoryCache(loadSrc: string,option: ImageKnifeOption, engineKey: IEngineKey): ImageKnifeData | undefined {
|
||||||
let keys = engineKey.generateMemoryKey(loadSrc,option)
|
let memoryKey = engineKey.generateMemoryKey(loadSrc, ImageKnifeRequestSource.SRC, option)
|
||||||
return ImageKnife.getInstance()
|
return ImageKnife.getInstance()
|
||||||
.loadFromMemoryCache(keys)
|
.loadFromMemoryCache(memoryKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
private readFileCache(loadSrc:string,engineKey:IEngineKey,onComplete:(data:ImageKnifeData | undefined)=>void){
|
private readFileCache(loadSrc:string,engineKey:IEngineKey,onComplete:(data:ImageKnifeData | undefined)=>void){
|
||||||
|
|
|
@ -44,11 +44,11 @@ export class ImageKnifeDispatcher {
|
||||||
// 执行中的请求
|
// 执行中的请求
|
||||||
executingJobMap: LightWeightMap<string, List<ImageKnifeRequestWithSource>> = new LightWeightMap();
|
executingJobMap: LightWeightMap<string, List<ImageKnifeRequestWithSource>> = new LightWeightMap();
|
||||||
// 开发者可配置全局缓存
|
// 开发者可配置全局缓存
|
||||||
private engineKeyImpl: IEngineKey = new DefaultEngineKey();
|
private engineKey: IEngineKey = new DefaultEngineKey();
|
||||||
|
|
||||||
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean {
|
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean {
|
||||||
let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance()
|
let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance()
|
||||||
.loadFromMemoryCache(this.engineKeyImpl.generateMemoryKey(imageSrc, request.imageKnifeOption))
|
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption))
|
||||||
if (memoryCache !== undefined) {
|
if (memoryCache !== undefined) {
|
||||||
// 画主图
|
// 画主图
|
||||||
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||||
|
@ -97,13 +97,12 @@ export class ImageKnifeDispatcher {
|
||||||
* 获取和显示图片
|
* 获取和显示图片
|
||||||
*/
|
*/
|
||||||
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): void {
|
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): void {
|
||||||
let keyMemory: string = this.engineKeyImpl.generateMemoryKey(imageSrc, currentRequest.imageKnifeOption)
|
let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc,requestSource, currentRequest.imageKnifeOption)
|
||||||
let keyFile: string = this.engineKeyImpl.generateFileKey(imageSrc, currentRequest.imageKnifeOption.signature)
|
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
|
||||||
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(keyMemory)
|
|
||||||
if (requestList == undefined) {
|
if (requestList == undefined) {
|
||||||
requestList = new List()
|
requestList = new List()
|
||||||
requestList.add({ request: currentRequest, source: requestSource })
|
requestList.add({ request: currentRequest, source: requestSource })
|
||||||
this.executingJobMap.set(keyMemory, requestList)
|
this.executingJobMap.set(memoryKey, requestList)
|
||||||
} else {
|
} else {
|
||||||
requestList.add({ request: currentRequest, source: requestSource })
|
requestList.add({ request: currentRequest, source: requestSource })
|
||||||
return
|
return
|
||||||
|
@ -112,13 +111,14 @@ export class ImageKnifeDispatcher {
|
||||||
let request: RequestJobRequest = {
|
let request: RequestJobRequest = {
|
||||||
context: currentRequest.context,
|
context: currentRequest.context,
|
||||||
src: imageSrc,
|
src: imageSrc,
|
||||||
key: keyFile,
|
|
||||||
headers:currentRequest.imageKnifeOption.headerOption,
|
headers:currentRequest.imageKnifeOption.headerOption,
|
||||||
allHeaders:currentRequest.headers,
|
allHeaders:currentRequest.headers,
|
||||||
customGetImage: currentRequest.imageKnifeOption.customGetImage,
|
customGetImage: currentRequest.imageKnifeOption.customGetImage,
|
||||||
onlyRetrieveFromCache: currentRequest.imageKnifeOption.onlyRetrieveFromCache,
|
onlyRetrieveFromCache: currentRequest.imageKnifeOption.onlyRetrieveFromCache,
|
||||||
transformation:currentRequest.imageKnifeOption.transformation,
|
transformation:currentRequest.imageKnifeOption.transformation,
|
||||||
writeCacheStrategy: currentRequest.imageKnifeOption.writeCacheStrategy,
|
writeCacheStrategy: currentRequest.imageKnifeOption.writeCacheStrategy,
|
||||||
|
engineKey: this.engineKey,
|
||||||
|
signature: currentRequest.imageKnifeOption.signature,
|
||||||
requestSource
|
requestSource
|
||||||
}
|
}
|
||||||
// 启动线程下载和解码主图
|
// 启动线程下载和解码主图
|
||||||
|
@ -144,15 +144,15 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.executingJobMap.remove(keyMemory)
|
this.executingJobMap.remove(memoryKey)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogUtil.log("error: no requestlist need to draw for key = " + keyMemory)
|
LogUtil.log("error: no requestlist need to draw for key = " + memoryKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 保存文件缓存
|
// 保存文件缓存
|
||||||
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
|
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
|
||||||
ImageKnife.getInstance().saveWithoutWriteFile(keyFile, requestJobResult.bufferSize)
|
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
let ImageKnifeData: ImageKnifeData = {
|
let ImageKnifeData: ImageKnifeData = {
|
||||||
|
@ -164,7 +164,7 @@ export class ImageKnifeDispatcher {
|
||||||
// 保存内存缓存
|
// 保存内存缓存
|
||||||
if(currentRequest.imageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.File) {
|
if(currentRequest.imageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.File) {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.saveMemoryCache(this.engineKeyImpl.generateMemoryKey(imageSrc, currentRequest.imageKnifeOption),
|
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption),
|
||||||
ImageKnifeData)
|
ImageKnifeData)
|
||||||
}
|
}
|
||||||
if (requestList !== undefined) {
|
if (requestList !== undefined) {
|
||||||
|
@ -190,11 +190,11 @@ export class ImageKnifeDispatcher {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.executingJobMap.remove(keyMemory)
|
this.executingJobMap.remove(memoryKey)
|
||||||
this.dispatchNextJob()
|
this.dispatchNextJob()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogUtil.log("error: no requestlist need to draw for key = " + keyMemory)
|
LogUtil.log("error: no requestlist need to draw for key = " + memoryKey)
|
||||||
}
|
}
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
setEngineKeyImpl(impl: IEngineKey): void {
|
setEngineKeyImpl(impl: IEngineKey): void {
|
||||||
this.engineKeyImpl = impl;
|
this.engineKey = impl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,10 +235,13 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
||||||
totalSize: number = 2000
|
totalSize: number = 2000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成文件key
|
||||||
|
let fileKey = request.engineKey.generateFileKey(request.src, request.signature)
|
||||||
|
|
||||||
// 判断自定义下载
|
// 判断自定义下载
|
||||||
if (request.customGetImage !== undefined && typeof request.src === 'string' && (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0)) {
|
if (request.customGetImage !== undefined && typeof request.src === 'string' && (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0)) {
|
||||||
// 先从文件缓存获取
|
// 先从文件缓存获取
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, request.key)
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey)
|
||||||
if (resBuf === undefined) {
|
if (resBuf === undefined) {
|
||||||
LogUtil.log("customGetImage customGetImage");
|
LogUtil.log("customGetImage customGetImage");
|
||||||
resBuf = await request.customGetImage(request.context, request.src)
|
resBuf = await request.customGetImage(request.context, request.src)
|
||||||
|
@ -246,7 +249,7 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
||||||
if (resBuf !== undefined) {
|
if (resBuf !== undefined) {
|
||||||
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug,不能直接获取resBuf.byteLength
|
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug,不能直接获取resBuf.byteLength
|
||||||
bufferSize = copyBuf.byteLength
|
bufferSize = copyBuf.byteLength
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, request.key, resBuf)
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,13 +257,8 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
||||||
if (typeof request.src === 'string') {
|
if (typeof request.src === 'string') {
|
||||||
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
|
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
|
||||||
// 先从文件缓存获取
|
// 先从文件缓存获取
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, request.key)
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey)
|
||||||
if (resBuf === undefined && request.onlyRetrieveFromCache != true && request.requestSource == 0) {
|
if (resBuf === undefined && request.onlyRetrieveFromCache != true && request.requestSource == 0) {
|
||||||
// // 模拟耗时验证
|
|
||||||
// let start = (new Date()).getTime();
|
|
||||||
// while ((new Date()).getTime() - start < 5000) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
let httpRequest = http.createHttp();
|
let httpRequest = http.createHttp();
|
||||||
let progress: number = 0
|
let progress: number = 0
|
||||||
const headerObj: Record<string,object> = {}
|
const headerObj: Record<string,object> = {}
|
||||||
|
@ -309,11 +307,11 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
||||||
if (resBuf !== undefined && request.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
|
if (resBuf !== undefined && request.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
|
||||||
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug,不能直接获取resBuf.byteLength
|
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug,不能直接获取resBuf.byteLength
|
||||||
bufferSize = copyBuf.byteLength
|
bufferSize = copyBuf.byteLength
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, request.key, resBuf)
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LogUtil.log("success get image from filecache for key = " + request.key);
|
LogUtil.log("success get image from filecache for key = " + fileKey);
|
||||||
}
|
}
|
||||||
} else { //从本地文件获取
|
} else { //从本地文件获取
|
||||||
let stat = fs.statSync(request.src);
|
let stat = fs.statSync(request.src);
|
||||||
|
@ -346,7 +344,8 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
||||||
let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(resBuf))
|
let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(resBuf))
|
||||||
return {
|
return {
|
||||||
pixelMap: base64str,
|
pixelMap: base64str,
|
||||||
bufferSize: bufferSize
|
bufferSize: bufferSize,
|
||||||
|
fileKey: fileKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +368,8 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pixelMap: resPixelmap,
|
pixelMap: resPixelmap,
|
||||||
bufferSize: bufferSize
|
bufferSize: bufferSize,
|
||||||
|
fileKey: fileKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,12 +389,12 @@ export interface ImageKnifeRequestWithSource {
|
||||||
interface RequestJobResult {
|
interface RequestJobResult {
|
||||||
pixelMap: PixelMap | string | undefined
|
pixelMap: PixelMap | string | undefined
|
||||||
bufferSize: number
|
bufferSize: number
|
||||||
|
fileKey: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RequestJobRequest {
|
interface RequestJobRequest {
|
||||||
context: common.UIAbilityContext,
|
context: common.UIAbilityContext,
|
||||||
src: string | PixelMap | Resource,
|
src: string | PixelMap | Resource,
|
||||||
key: string,
|
|
||||||
headers?:Array<HeaderOptions>,
|
headers?:Array<HeaderOptions>,
|
||||||
allHeaders:Map<string,Object>,
|
allHeaders:Map<string,Object>,
|
||||||
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>,
|
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>,
|
||||||
|
@ -402,4 +402,6 @@ interface RequestJobRequest {
|
||||||
requestSource:ImageKnifeRequestSource
|
requestSource:ImageKnifeRequestSource
|
||||||
transformation?: PixelMapTransformation
|
transformation?: PixelMapTransformation
|
||||||
writeCacheStrategy?: WriteCacheStrategyType
|
writeCacheStrategy?: WriteCacheStrategyType
|
||||||
|
signature?: string
|
||||||
|
engineKey:IEngineKey
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
*/
|
*/
|
||||||
import taskpool from '@ohos.taskpool';
|
import taskpool from '@ohos.taskpool';
|
||||||
import common from '@ohos.app.ability.common'
|
import common from '@ohos.app.ability.common'
|
||||||
import { ObjectKey } from './model/ObjectKey';
|
|
||||||
import { WriteCacheStrategyType } from './model/ImageKnifeData';
|
import { WriteCacheStrategyType } from './model/ImageKnifeData';
|
||||||
import { PixelMapTransformation } from './transform/PixelMapTransformation';
|
import { PixelMapTransformation } from './transform/PixelMapTransformation';
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ export class ImageKnifeOption {
|
||||||
headerOption?: Array<HeaderOptions>;
|
headerOption?: Array<HeaderOptions>;
|
||||||
|
|
||||||
// 自定义缓存关键字
|
// 自定义缓存关键字
|
||||||
signature?: ObjectKey;
|
signature?: string;
|
||||||
|
|
||||||
objectFit?: ImageFit
|
objectFit?: ImageFit
|
||||||
|
|
||||||
|
|
|
@ -12,48 +12,36 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import util from '@ohos.util';
|
|
||||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
||||||
import { ImageKnifeOption } from '../ImageKnifeOption';
|
import { ImageKnifeOption } from '../ImageKnifeOption';
|
||||||
import { IEngineKey } from './IEngineKey';
|
import { IEngineKey } from './IEngineKey';
|
||||||
import { ObjectKey } from '../model/ObjectKey';
|
|
||||||
import { PixelMapTransformation } from '../transform/PixelMapTransformation';
|
import { PixelMapTransformation } from '../transform/PixelMapTransformation';
|
||||||
|
import { ImageKnifeRequestSource } from '../ImageKnifeDispatcher';
|
||||||
|
|
||||||
|
@Sendable
|
||||||
export class DefaultEngineKey implements IEngineKey {
|
export class DefaultEngineKey implements IEngineKey {
|
||||||
private memoryKeyCache: util.LRUCache<string, string> = new util.LRUCache(1024)
|
|
||||||
private fileKeyCache: util.LRUCache<string, string> = new util.LRUCache(1024)
|
|
||||||
|
|
||||||
// 生成内存缓存key
|
// 生成内存缓存key
|
||||||
generateMemoryKey(loadSrc: string | PixelMap | Resource, imageKnifeOption: ImageKnifeOption): string {
|
generateMemoryKey(loadSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,
|
||||||
let src = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
imageKnifeOption: ImageKnifeOption, width?: number, height?: number): string {
|
||||||
if (imageKnifeOption.signature) {
|
let key = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
||||||
src += "signature=" + imageKnifeOption.signature.getKey() + ";"
|
if (requestSource === ImageKnifeRequestSource.SRC) {
|
||||||
|
if (imageKnifeOption.signature !== undefined && imageKnifeOption.signature !== "") {
|
||||||
|
key += "signature=" + imageKnifeOption.signature + ";"
|
||||||
|
}
|
||||||
|
if (imageKnifeOption.transformation) {
|
||||||
|
key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (imageKnifeOption.transformation) {
|
return key
|
||||||
src += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";"
|
|
||||||
}
|
|
||||||
return this.generateKey(src, this.memoryKeyCache)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成文件缓存key
|
// 生成文件缓存key
|
||||||
generateFileKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string {
|
generateFileKey(loadSrc: string | PixelMap | Resource, signature?: string): string {
|
||||||
let src = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
let src = "loadSrc=" + (typeof loadSrc == "string" ? loadSrc : JSON.stringify(loadSrc)) + ";"
|
||||||
if (signature) {
|
if (signature !== undefined && signature !== "") {
|
||||||
src += "signature=" + signature.getKey() + ";"
|
src += "signature=" + signature + ";"
|
||||||
}
|
|
||||||
return this.generateKey(src, this.fileKeyCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// key缓存策略,避免无意义的 JSON.stringify
|
|
||||||
private generateKey(keyCache: string, cache: util.LRUCache<string, string>): string {
|
|
||||||
let result = cache.get(keyCache)
|
|
||||||
if (result != undefined) {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result = SparkMD5.hashBinary(keyCache)
|
|
||||||
cache.put(keyCache, result)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
return SparkMD5.hashBinary(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTransformation(transformation: PixelMapTransformation): string {
|
private getTransformation(transformation: PixelMapTransformation): string {
|
||||||
|
|
|
@ -12,15 +12,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import { ImageKnifeRequestSource } from '../ImageKnifeDispatcher'
|
||||||
import { ImageKnifeOption } from '../ImageKnifeOption'
|
import { ImageKnifeOption } from '../ImageKnifeOption'
|
||||||
import { ObjectKey } from '../model/ObjectKey'
|
|
||||||
|
|
||||||
export interface IEngineKey {
|
export interface IEngineKey {
|
||||||
// 生成内存缓存key
|
// 生成内存缓存key
|
||||||
generateMemoryKey(loadSrc: string | PixelMap | Resource, imageKnifeOption: ImageKnifeOption): string
|
generateMemoryKey(loadSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,
|
||||||
|
imageKnifeOption: ImageKnifeOption, width?: number, height?: number): string
|
||||||
|
|
||||||
// 生成文件缓存key
|
// 生成文件缓存key
|
||||||
generateFileKey(loadSrc: string | PixelMap | Resource, signature?: ObjectKey | undefined): string
|
generateFileKey(loadSrc: string | PixelMap | Resource, signature?: string): string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 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 ObjectKey{
|
|
||||||
|
|
||||||
private objectKey: string;
|
|
||||||
|
|
||||||
constructor(objectKey: string) {
|
|
||||||
this.objectKey = objectKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
getKey(): string{
|
|
||||||
return this.objectKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -31,7 +31,7 @@ export class FileCache {
|
||||||
maxSize: number = 0
|
maxSize: number = 0
|
||||||
path: string = ""
|
path: string = ""
|
||||||
private lruCache: util.LRUCache<string, number>
|
private lruCache: util.LRUCache<string, number>
|
||||||
static isInited: boolean = false
|
private isInited: boolean = false
|
||||||
private context?: Context
|
private context?: Context
|
||||||
readonly defaultMaxSize: number = 512;
|
readonly defaultMaxSize: number = 512;
|
||||||
readonly defaultSize: number = 128;
|
readonly defaultSize: number = 128;
|
||||||
|
@ -57,7 +57,7 @@ export class FileCache {
|
||||||
* 遍历缓存文件目录,初始化缓存
|
* 遍历缓存文件目录,初始化缓存
|
||||||
*/
|
*/
|
||||||
public async initFileCache() {
|
public async initFileCache() {
|
||||||
if (FileCache.isInited) {
|
if (this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ export class FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.trimToSize();
|
this.trimToSize();
|
||||||
FileCache.isInited = true
|
this.isInited = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加缓存键值对,同时写文件
|
// 添加缓存键值对,同时写文件
|
||||||
|
@ -108,7 +108,7 @@ export class FileCache {
|
||||||
if (key == null || value == null) {
|
if (key == null || value == null) {
|
||||||
throw new Error('key or value is invalid ');
|
throw new Error('key or value is invalid ');
|
||||||
}
|
}
|
||||||
if (!FileCache.isInited) {
|
if (!this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ export class FileCache {
|
||||||
if (key == null || value == null) {
|
if (key == null || value == null) {
|
||||||
throw new Error('key or value is invalid ');
|
throw new Error('key or value is invalid ');
|
||||||
}
|
}
|
||||||
if (!FileCache.isInited) {
|
if (!this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ export class FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
get(key: string): ArrayBuffer | undefined {
|
get(key: string): ArrayBuffer | undefined {
|
||||||
if (!FileCache.isInited) {
|
if (!this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ export class FileCache {
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
throw new Error('key is null,checking the parameter');
|
throw new Error('key is null,checking the parameter');
|
||||||
}
|
}
|
||||||
if (!FileCache.isInited) {
|
if (!this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,10 +179,10 @@ export class FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeAll(): Promise<void> {
|
async removeAll(): Promise<void> {
|
||||||
if (!FileCache.isInited) {
|
if (!this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
FileCache.isInited = false
|
this.isInited = false
|
||||||
this.lruCache.clear()
|
this.lruCache.clear()
|
||||||
this.currentMemory = 0;
|
this.currentMemory = 0;
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ export class FileCache {
|
||||||
await FileUtils.getInstance().deleteFile(this.path + filenames[i])
|
await FileUtils.getInstance().deleteFile(this.path + filenames[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
FileCache.isInited = true
|
this.isInited = true
|
||||||
}
|
}
|
||||||
|
|
||||||
size(): number {
|
size(): number {
|
||||||
|
@ -242,9 +242,6 @@ export class FileCache {
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
static saveFileCacheOnlyFile(context: Context, key: string, value: ArrayBuffer): boolean {
|
static saveFileCacheOnlyFile(context: Context, key: string, value: ArrayBuffer): boolean {
|
||||||
if (!FileCache.isInited) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// 写文件
|
// 写文件
|
||||||
FileUtils.getInstance()
|
FileUtils.getInstance()
|
||||||
.writeFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + key, value)
|
.writeFileSync(context.cacheDir + FileUtils.SEPARATOR + FileCache.CACHE_FOLDER + FileUtils.SEPARATOR + key, value)
|
||||||
|
|
Loading…
Reference in New Issue