补充文件缓存预加载接口preLoadCache、getCacheImage,请求头,以及ImageKnifeOption属性写入缓存策略、onlyRetrieveFromCache,请求头

Signed-off-by: zgf <zenggaofeng2@h-partners.com>
This commit is contained in:
zgf 2024-04-30 16:30:58 +08:00
parent 219164b278
commit 915c9275b3
10 changed files with 161 additions and 124 deletions

View File

@ -1,10 +1,11 @@
## 3.0.0-rc.1
- 新增从内存或文件缓存获取图片数据接口isUrlExist
- 新增从内存或文件缓存获取图片数据接口getCacheImage
- 新增图片预加载preLoadCache并会犯文件缓存路径
- ImageKnifeOption新增writeCacheStrategy存入策略
- ImageKnifeOption新增writeCacheStrategy存入策略(只存入内存或文件缓存)
- ImageKnifeOption新增onlyRetrieveFromCache仅用缓存加载
- 新增单个和全局请求头
- 补齐自定key特性
- 获取组件宽高改用onSizeChange
## 3.0.0-rc.0
- 使用Image组件替换Canvas组件渲染并重构大部分的实现逻辑提升渲染性能

View File

@ -125,13 +125,13 @@ ImageKnifeComponent({ ImageKnifeOption:
### ImageKnifeOption参数列表
| 参数名称 | 入参内容 | 功能简介 |
|-----------------------|--------------------------------|---------------|
|-----------------------|-------------------------------|---------------|
| loadSrc | string、PixelMap、Resource | 主图展示 |
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
| objectFit | ImageFit | 图片展示样式(可选) |
| writeCacheStrategy | WriteCacheStrategy_Type | 写入缓存策略(可选) |
| onlyRetrieveFromCache | boolean | 仅使用缓存加载数据(可选) |
| writeCacheStrategy | WriteCacheStrategyType | 写入缓存策略(可选) |
| onlyRetrieveFromCache | boolean | 跳过网络和本地请求(可选) |
| customGetImage | (context: Context, src: string | 自定义网络(可选) | | Resource | 错误占位图数据源 |
| border | BorderOptions | 边框圆角(可选) |
| priority | taskpool.Priority | 加载优先级(可选) |
@ -142,10 +142,11 @@ ImageKnifeComponent({ ImageKnifeOption:
### ImageKnife接口
| 参数名称 | 入参内容 | 功能简介 |
|--------------|---------------------------|-------------|
|--------------|---------------------------|---------------|
| preLoadCache | url:string | 预加载并返回文件缓存路径 |
| isUrlExist | url: string, cacheType: Cache_Type | 从内存或文件缓存中获取资源 |
| addHeader | key: string, value: Object | 全局设置请求头 |
| getCacheImage | url: string, cacheType: CacheType | 从内存或文件缓存中获取资源 |
| addHeader | key: string, value: Object | 全局添加请求头属性 |
| serHeaderOptions | Array<HeaderOptions> | 全局设置请求头 |
| deleteHeader | key: string | 全局删除请求头 |
| setEngineKeyImpl | CustomEngineKeyImpl | 全局配置缓存key |

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption,ImageKnifeData,Cache_Type } from '@ohos/imageknife'
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption,ReadCacheStrategyType } from '@ohos/imageknife'
@Entry
@Component
@ -31,14 +31,14 @@ struct TestIsUrlExist {
})
Button("内存缓存获取gif").onClick(()=>{
ImageKnife.getInstance()
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",Cache_Type.MemoryCache)
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",ReadCacheStrategyType.Memory)
.then((data)=>{
this.source = data!.source
})
})
Button("文件缓存获取gif").onClick(()=>{
ImageKnife.getInstance()
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",Cache_Type.FileCache)
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",ReadCacheStrategyType.File)
.then((data)=>{
this.source1 = data!.source
})
@ -50,14 +50,14 @@ struct TestIsUrlExist {
})
Button("内存缓存获取").onClick(()=>{
ImageKnife.getInstance()
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',Cache_Type.MemoryCache)
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',Cache_Type.Memory)
.then((data)=>{
this.source = data!.source
})
})
Button("文件缓存获取").onClick(()=>{
ImageKnife.getInstance()
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',Cache_Type.FileCache)
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',Cache_Type.File)
.then((data)=>{
this.source1 = data!.source
})

View File

@ -14,7 +14,7 @@ export { IEngineKey } from './src/main/ets/key/IEngineKey'
export { ObjectKey } from './src/main/ets/model/ObjectKey'
export { ImageKnifeData , Cache_Type} from "./src/main/ets/model/ImageKnifeData"
export { ImageKnifeData , ReadCacheStrategyType} from "./src/main/ets/model/ImageKnifeData"

View File

@ -14,7 +14,7 @@
"main": "index.ets",
"repository": "https://gitee.com/openharmony-tpc/ImageKnife",
"type": "module",
"version": "3.0.0-rc.0",
"version": "3.0.0-rc.1",
"dependencies": {
},

View File

@ -13,13 +13,13 @@
* limitations under the License.
*/
import { ImageKnifeRequest } from './ImageKnifeRequest';
import { Cache_Type, ImageKnifeData } from './model/ImageKnifeData';
import { ReadCacheStrategyType, ImageKnifeData } from './model/ImageKnifeData';
import { MemoryLruCache } from './utils/MemoryLruCache';
import { IMemoryCache } from './utils/IMemoryCache'
import { FileCache } from './utils/FileCache';
import { ImageKnifeDispatcher } from './ImageKnifeDispatcher';
import { IEngineKey } from './key/IEngineKey';
import { ImageKnifeOption } from './ImageKnifeOption';
import { HeaderOptions, ImageKnifeOption } from './ImageKnifeOption';
import { DefaultEngineKey } from './key/DefaultEngineKey';
import { FileTypeUtil } from './utils/FileTypeUtil';
import { util } from '@kit.ArkTS';
@ -56,11 +56,27 @@ export class ImageKnife {
this.fileCache = new FileCache(context, size, memory)
this.fileCache.initFileCache()
}
//全局设置请求头调用方法
/**
* 全局添加单个请求头
* @param key 请求头属性
* @param value 请求头值
*/
addHeader(key: string, value: Object) {
this.headerMap.set(key, value);
}
/**
* 全局设置请求头调用方法
* @param options 请求头数组
*/
serHeaderOptions(options:Array<HeaderOptions>) {
options.forEach((value)=>{
this.headerMap.set(value.key,value.value)
})
}
/**
* 删除单个请求头属性
* @param key 请求头属性
*/
deleteHeader(key: string) {
this.headerMap.delete(key);
}
@ -103,13 +119,17 @@ export class ImageKnife {
getFileCache(): FileCache{
return this.fileCache as FileCache
}
// 预加载到文件缓存,并返回缓存路径
preLoadCache(url:string): Promise<string> {
/**
* 预加载到缓存
* @param loadSrc 图片地址url
* @returns 返回文件缓存路径
*/
preLoadCache(loadSrc:string): Promise<string> {
return new Promise((resolve,reject)=>{
let imageKnifeOption = new ImageKnifeOption()
imageKnifeOption.loadSrc = url
imageKnifeOption.loadSrc = loadSrc
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
let keys = engineKeyImpl.generateCacheKey(url)
let keys = engineKeyImpl.generateCacheKey(loadSrc)
let cachePath = ImageKnife.getInstance().getFileCache().getFileToPath(keys)
if(cachePath == null || cachePath == "" || cachePath == undefined) {
let request = new ImageKnifeRequest(
@ -120,12 +140,7 @@ export class ImageKnife {
0,
{
showPixelMap(version: number, pixelMap: PixelMap | string) {
let cachePaths = ImageKnife.getInstance().getFileCache().getFileToPath(keys)
if(cachePaths != "") {
resolve(cachePaths)
} else {
reject(undefined)
}
resolve(ImageKnife.getInstance().getFileCache().getFileToPath(keys))
}
}
)
@ -135,17 +150,32 @@ export class ImageKnife {
}
})
}
// 从内存或文件缓存中获取资源
getCacheImage(url: string, cacheType: Cache_Type):Promise<ImageKnifeData | undefined> {
/**
* 从内存或文件缓存中获取图片数据
* @param url 图片地址url
* @param cacheType 缓存策略
* @returns 图片数据
*/
getCacheImage(loadSrc: string, cacheType: ReadCacheStrategyType = ReadCacheStrategyType.Default):Promise<ImageKnifeData | undefined> {
return new Promise((resolve,reject)=>{
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
if(cacheType == Cache_Type.MemoryCache) {
let keys = engineKeyImpl.generateCacheKey(url)
let memoryCache:ImageKnifeData | undefined = ImageKnife.getInstance()
if(cacheType == ReadCacheStrategyType.Memory) {
resolve(this.ReadMemoryCache(loadSrc,engineKeyImpl))
} else if (cacheType == ReadCacheStrategyType.File) {
this.ReadFileCache(loadSrc,engineKeyImpl,resolve)
} else {
let data = this.ReadMemoryCache(loadSrc,engineKeyImpl)
data == undefined ? this.ReadFileCache(loadSrc,engineKeyImpl,resolve) : data
}
})
}
ReadMemoryCache(loadSrc:string,engineKey:IEngineKey): ImageKnifeData | undefined{
let keys = engineKey.generateCacheKey(loadSrc)
return ImageKnife.getInstance()
.loadFromMemoryCache(keys)
resolve(memoryCache)
} else if (cacheType == Cache_Type.FileCache) {
let keys = engineKeyImpl.generateCacheKey(url)
}
ReadFileCache(loadSrc:string,engineKey:IEngineKey,onComplete:(data:ImageKnifeData | undefined)=>void){
let keys = engineKey.generateCacheKey(loadSrc)
let buffer = ImageKnife.getInstance().loadFromFileCache(keys)
if(buffer != undefined) {
let fileTypeUtil = new FileTypeUtil();
@ -154,7 +184,7 @@ export class ImageKnife {
let base64Help = new util.Base64Helper()
let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(buffer))
resolve({
onComplete({
source:base64str,
imageWidth: 0,
imageHeight: 0
@ -168,7 +198,7 @@ export class ImageKnife {
imageSource.createPixelMap(decodingOptions)
.then((pixelmap: PixelMap) => {
resolve({
onComplete({
source:pixelmap,
imageWidth: 0,
imageHeight: 0
@ -176,11 +206,9 @@ export class ImageKnife {
imageSource.release()
})
} else {
resolve(undefined)
onComplete(undefined)
}
}
})
}
/**
* 清除所有文件缓存
* @returns

View File

@ -23,7 +23,7 @@ import common from '@ohos.app.ability.common';
import { FileCache } from './utils/FileCache';
import fs from '@ohos.file.fs';
import { ImageKnife } from './ImageKnife';
import { ImageKnifeData, WriteCacheStrategy_Type } from './model/ImageKnifeData';
import { ImageKnifeData, WriteCacheStrategyType } from './model/ImageKnifeData';
import http from '@ohos.net.http';
import image from '@ohos.multimedia.image';
import emitter from '@ohos.events.emitter';
@ -147,7 +147,7 @@ export class ImageKnifeDispatcher {
}
}
// 保存文件缓存
if (requestJobResult.bufferSize > 0) {
if (requestJobResult.bufferSize > 0 && currentRequest.ImageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
ImageKnife.getInstance().saveWithoutWriteFile(key, requestJobResult.bufferSize)
}
@ -158,7 +158,7 @@ export class ImageKnifeDispatcher {
}
// 保存内存缓存
if(currentRequest.ImageKnifeOption.writeCacheStrategy !== WriteCacheStrategy_Type.OnlyFile) {
if(currentRequest.ImageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.File) {
ImageKnife.getInstance()
.saveMemoryCache(this.engineKeyImpl.generateCacheKey(imageSrc, currentRequest.ImageKnifeOption.signature),
ImageKnifeData)

View File

@ -15,7 +15,7 @@
import taskpool from '@ohos.taskpool';
import common from '@ohos.app.ability.common'
import { ObjectKey } from './model/ObjectKey';
import { WriteCacheStrategy_Type } from './model/ImageKnifeData';
import { WriteCacheStrategyType } from './model/ImageKnifeData';
export interface HeaderOptions {
key: string;
value: Object;
@ -40,7 +40,7 @@ export class ImageKnifeOption {
border?: BorderOptions
// 缓存策略
writeCacheStrategy?: WriteCacheStrategy_Type
writeCacheStrategy?: WriteCacheStrategyType
// 仅使用缓存加载数据
onlyRetrieveFromCache?: boolean = false;

View File

@ -35,10 +35,6 @@ export struct ImageKnifeComponent {
private currentHeight: number = 0
private componentVersion: number = 0
private currentContext: common.UIAbilityContext | undefined = undefined
@State keyCanvas: KeyCanvas = {
keyId: util.generateRandomUUID()
}
private listener: inspector.ComponentObserver = inspector.createComponentObserver(this.keyCanvas.keyId)
aboutToAppear(): void {
//闪动问题失效,注释相应代码后续修复
@ -50,7 +46,6 @@ export struct ImageKnifeComponent {
// this.pixelMap = memoryCache.source;
// }else {
LogUtil.log("aboutToAppear onLayoutComplete")
this.listener.on("layout", this.onLayoutComplete)
// }
}
@ -60,21 +55,36 @@ export struct ImageKnifeComponent {
this.request.requestState = ImageKnifeRequestState.DESTROY
this.request = undefined
}
this.listener.off("layout", this.onLayoutComplete)
}
aboutToRecycle(){
aboutToRecycle() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
this.request = undefined
}
}
build() {
Image(this.pixelMap)
.objectFit(this.ImageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.ImageKnifeOption.objectFit)
.width(this.adaptiveWidth)
.height(this.adaptiveHeight)
.key(this.keyCanvas.keyId)
.border(this.ImageKnifeOption.border)
.onSizeChange((oldValue:SizeOptions, newValue:SizeOptions) => {
this.currentWidth = newValue.width as number
this.currentHeight = newValue.height as number
this.lastWidth = oldValue.width as number
this.lastHeight = oldValue.height as number
if (this.currentWidth <= 0 || this.currentHeight <= 0) {
// 存在宽或者高为0,此次重回无意义,无需进行request请求
} else {
// 前提:宽高值均有效,值>0. 条件1当前宽高与上一次宽高不同 条件2:当前是第一次绘制
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight)
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
}
})
}
watchImageKnifeOption() {
@ -85,12 +95,14 @@ export struct ImageKnifeComponent {
this.componentVersion++
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
getCurrentContext(): common.UIAbilityContext{
if(this.currentContext == undefined) {
getCurrentContext(): common.UIAbilityContext {
if (this.currentContext == undefined) {
this.currentContext = getContext(this) as common.UIAbilityContext
}
return this.currentContext
}
getRequest(width: number, height: number): ImageKnifeRequest {
if (this.request == undefined) {
this.request = new ImageKnifeRequest(
@ -130,23 +142,6 @@ export struct ImageKnifeComponent {
return this.request
}
onLayoutComplete: () => void = (): void => {
let value: componentUtils.ComponentInfo = componentUtils.getRectangleById(this.keyCanvas.keyId);
this.currentWidth = px2vp(value.size.width)
this.currentHeight = px2vp(value.size.height)
if (this.currentWidth <= 0 || this.currentHeight <= 0) {
// 存在宽或者高为0,此次重回无意义,无需进行request请求
} else {
// 前提:宽高值均有效,值>0. 条件1当前宽高与上一次宽高不同 条件2:当前是第一次绘制
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
this.lastWidth = this.currentWidth
this.lastHeight = this.currentHeight
LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight)
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
}
}
}
interface KeyCanvas {

View File

@ -17,14 +17,26 @@ export interface ImageKnifeData {
imageWidth: number,
imageHeight: number
}
export enum Cache_Type {
// 内存缓存
MemoryCache = 0,
// 文件缓存
FileCache = 1
/**
* 读取缓存策略
*/
export enum ReadCacheStrategyType {
// 默认-读取内存和文件缓存
Default = 0,
// 只读取内存缓存
Memory = 1,
// 只读取文件缓存
File = 2
}
export enum WriteCacheStrategy_Type {
DEFAULT = 0,// 默认都开启
OnlyFile = 1 // 仅缓存文件
/**
* 写入缓存策略
*/
export enum WriteCacheStrategyType {
// 默认-写入内存和文件缓存
Default = 0,
// 只写入内存缓存
Memory = 1,
// 只写入文件缓存
File = 2
}