1.补充option参数:placeholderObjectFit,errorholderObjectFit分别支持占位图填充效果和错误图填充效果

2.合并读写缓存策略CacheStrategy

Signed-off-by: madixin <madixin@huawei.com>
This commit is contained in:
madixin 2024-05-07 15:31:54 +08:00
parent 8b4ba78d56
commit dd24720c00
13 changed files with 139 additions and 59 deletions

View File

@ -1,6 +1,7 @@
## 3.0.0-rc.3
- 将请求默认并行从64调整到8减少对taskpool execute内存消耗
- 补充option参数placeholderObjectFiterrorholderObjectFit分别支持占位图填充效果和错误图填充效果
## 3.0.0-rc.2
- 新增支持使用一个或多个图片变换,如模糊,高亮等

View File

@ -138,22 +138,24 @@ ImageKnifeComponent({ ImageKnifeOption:
## 接口说明
### ImageKnifeOption参数列表
| 参数名称 | 入参内容 | 功能简介 |
|-----------------------|--------------------------------|-----------------|
| loadSrc | string、PixelMap、Resource | 主图展示 |
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
| objectFit | ImageFit | 图片展示样式(可选) |
| writeCacheStrategy | WriteCacheStrategyType | 写入缓存策略(可选) |
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
| 参数名称 | 入参内容 | 功能简介 |
|-----------------------|---------------------------|-----------------|
| loadSrc | string、PixelMap、Resource | 主图展示 |
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
| objectFit | ImageFit | 主图填充效果(可选) |
| placeholderObjectFit | ImageFit | 占位图填充效果(可选) |
| errorholderObjectFit | ImageFit | 错误图填充效果(可选) |
| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) |
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
| border | BorderOptions | 边框圆角(可选) |
| priority | taskpool.Priority | 加载优先级(可选) |
| context | common.UIAbilityContext | 上下文(可选) |
| progressListener | (progress: number)=>void | 进度(可选) |
| signature | String | 自定义缓存关键字(可选) |
| headerOption | Array<HeaderOptions> | 设置请求头(可选) |
| transformation | PixelMapTransformation | 图片变换(可选) |
| border | BorderOptions | 边框圆角(可选) |
| priority | taskpool.Priority | 加载优先级(可选) |
| context | common.UIAbilityContext | 上下文(可选) |
| progressListener | (progress: number)=>void | 进度(可选) |
| signature | String | 自定义缓存关键字(可选) |
| headerOption | Array<HeaderOptions> | 设置请求头(可选) |
| transformation | PixelMapTransformation | 图片变换(可选) |
### ImageKnife接口
| 参数名称 | 入参内容 | 功能简介 |

View File

@ -92,6 +92,15 @@ struct Index {
uri: 'pages/ImageTransformation',
});
})
Button("不同的ObjectFit").margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/ObjectFitPage',
});
})
}

View File

@ -0,0 +1,57 @@
import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'
@Entry
@Component
struct ObjectFitPage {
@State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill
}
build() {
Column() {
Button("主图Fill拉伸填充").onClick(()=>{
this.imageKnifeOption = {
loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill
}
})
Button("占位图Contain保持比例填充").margin({top:10}).onClick(async () => {
ImageKnife.getInstance().removeAllMemoryCache()
await ImageKnife.getInstance().removeAllFileCache()
this.imageKnifeOption = {
loadSrc: "https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg",
placeholderSrc: $r("app.media.app_icon"),
errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill,
placeholderObjectFit: ImageFit.Contain
}
})
Button("错误图None不变化").margin({top:10}).onClick(() => {
this.imageKnifeOption = {
loadSrc: "http://xxxxx",
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill,
errorholderObjectFit: ImageFit.None
}
})
ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption
}).width(300).height(200).border({width:1}).margin({top:50})
}
.height('100%')
.width('100%')
}
}

View File

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

View File

@ -12,6 +12,7 @@
"pages/TestPrefetchToFileCache",
"pages/TestIsUrlExist",
"pages/TestHeader",
"pages/ImageTransformation"
"pages/ImageTransformation",
"pages/ObjectFitPage"
]
}

View File

@ -12,7 +12,7 @@ export { LogUtil } from './src/main/ets/utils/LogUtil'
export { IEngineKey } from './src/main/ets/key/IEngineKey'
export { ImageKnifeData , ReadCacheStrategyType} from "./src/main/ets/model/ImageKnifeData"
export { ImageKnifeData , CacheStrategy} from "./src/main/ets/model/ImageKnifeData"
export { PixelMapTransformation } from './src/main/ets/transform/PixelMapTransformation'

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
import { ImageKnifeRequest } from './ImageKnifeRequest';
import { ReadCacheStrategyType, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData';
import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData';
import { MemoryLruCache } from './utils/MemoryLruCache';
import { IMemoryCache } from './utils/IMemoryCache'
import { FileCache } from './utils/FileCache';
@ -166,16 +166,16 @@ export class ImageKnife {
* @returns 图片数据
*/
getCacheImage(loadSrc: string,
cacheType: ReadCacheStrategyType = ReadCacheStrategyType.Default): Promise<ImageKnifeData | undefined> {
cacheType: CacheStrategy = CacheStrategy.Default): Promise<ImageKnifeData | undefined> {
let option: ImageKnifeOption = {
loadSrc: loadSrc
}
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
return new Promise((resolve, reject) => {
if (cacheType == ReadCacheStrategyType.Memory) {
if (cacheType == CacheStrategy.Memory) {
resolve(this.readMemoryCache(loadSrc, option, engineKeyImpl))
} else if (cacheType == ReadCacheStrategyType.File) {
} else if (cacheType == CacheStrategy.File) {
this.readFileCache(loadSrc, engineKeyImpl, resolve)
} else {
let data = this.readMemoryCache(loadSrc, option, engineKeyImpl)

View File

@ -22,7 +22,7 @@ import buffer from '@ohos.buffer';
import { FileCache } from './utils/FileCache';
import fs from '@ohos.file.fs';
import { ImageKnife } from './ImageKnife';
import { ImageKnifeData, WriteCacheStrategyType } from './model/ImageKnifeData';
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData';
import http from '@ohos.net.http';
import image from '@ohos.multimedia.image';
import emitter from '@ohos.events.emitter';
@ -50,7 +50,7 @@ export class ImageKnifeDispatcher {
if (memoryCache !== undefined) {
// 画主图
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source)
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, requestSource)
if (requestSource == ImageKnifeRequestSource.SRC) {
request.requestState = ImageKnifeRequestState.COMPLETE
@ -114,7 +114,7 @@ export class ImageKnifeDispatcher {
customGetImage: currentRequest.imageKnifeOption.customGetImage,
onlyRetrieveFromCache: currentRequest.imageKnifeOption.onlyRetrieveFromCache,
transformation:currentRequest.imageKnifeOption.transformation,
writeCacheStrategy: ImageKnife.getInstance().isFileCacheInit() ? currentRequest.imageKnifeOption.writeCacheStrategy : WriteCacheStrategyType.Memory, // 未初始化文件缓存时,不写文件缓存
writeCacheStrategy: ImageKnife.getInstance().isFileCacheInit() ? currentRequest.imageKnifeOption.writeCacheStrategy : CacheStrategy.Memory, // 未初始化文件缓存时,不写文件缓存
engineKey: this.engineKey,
signature: currentRequest.imageKnifeOption.signature,
requestSource
@ -149,7 +149,7 @@ export class ImageKnifeDispatcher {
}
}
// 保存文件缓存
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) {
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize)
}
@ -160,7 +160,7 @@ export class ImageKnifeDispatcher {
}
// 保存内存缓存
if(currentRequest.imageKnifeOption.writeCacheStrategy !== WriteCacheStrategyType.File) {
if(currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) {
ImageKnife.getInstance()
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption),
ImageKnifeData)
@ -177,7 +177,7 @@ export class ImageKnifeDispatcher {
if (requestWithSource.source === ImageKnifeRequestSource.SRC || requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER && requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, ImageKnifeData.source)
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, ImageKnifeData.source, requestWithSource.source)
}
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
@ -244,7 +244,7 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
LogUtil.log("customGetImage customGetImage");
resBuf = await request.customGetImage(request.context, request.src)
// 保存文件缓存
if (resBuf !== undefined && request.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug不能直接获取resBuf.byteLength
bufferSize = copyBuf.byteLength
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf)
@ -302,7 +302,7 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
});
// 保存文件缓存
if (resBuf !== undefined && request.writeCacheStrategy !== WriteCacheStrategyType.Memory) {
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug不能直接获取resBuf.byteLength
bufferSize = copyBuf.byteLength
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf)

View File

@ -14,7 +14,7 @@
*/
import taskpool from '@ohos.taskpool';
import common from '@ohos.app.ability.common'
import { WriteCacheStrategyType } from './model/ImageKnifeData';
import { CacheStrategy } from './model/ImageKnifeData';
import { PixelMapTransformation } from './transform/PixelMapTransformation';
export interface HeaderOptions {
@ -35,13 +35,20 @@ export class ImageKnifeOption {
// 自定义缓存关键字
signature?: string;
// 主图填充效果
objectFit?: ImageFit
// 占位图填充效果
placeholderObjectFit?: ImageFit
// 错误图填充效果
errorholderObjectFit?: ImageFit
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>
border?: BorderOptions
// 缓存策略
writeCacheStrategy?: WriteCacheStrategyType
writeCacheStrategy?: CacheStrategy
// 仅使用缓存加载数据
onlyRetrieveFromCache?: boolean = false;

View File

@ -14,7 +14,7 @@
*/
import { ImageKnifeOption } from './ImageKnifeOption';
import common from '@ohos.app.ability.common';
import { ImageKnifeRequestSource } from './model/ImageKnifeData';
export class ImageKnifeRequest {
@ -63,5 +63,5 @@ export enum ImageKnifeRequestState {
export interface ImageKnifeRequestCallback {
showPixelMap: (version: number, pixelMap: PixelMap | string) => void;
showPixelMap: (version: number, pixelMap: PixelMap | string , requestSource: ImageKnifeRequestSource) => void;
}

View File

@ -17,6 +17,7 @@ import { ImageKnifeRequest, ImageKnifeRequestState } from '../ImageKnifeRequest'
import common from '@ohos.app.ability.common';
import { ImageKnife } from '../ImageKnife';
import { LogUtil } from '../utils/LogUtil';
import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
@Component
export struct ImageKnifeComponent {
@ -24,6 +25,7 @@ export struct ImageKnifeComponent {
@State pixelMap: PixelMap | string | undefined = undefined
@State adaptiveWidth: Length = '100%'
@State adaptiveHeight: Length = '100%'
@State objectFit: ImageFit = ImageFit.Contain
private request: ImageKnifeRequest | undefined
private lastWidth: number = 0
private lastHeight: number = 0
@ -41,9 +43,8 @@ export struct ImageKnifeComponent {
// //画主图
// this.pixelMap = memoryCache.source;
// }else {
LogUtil.log("aboutToAppear onLayoutComplete")
// }
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
}
aboutToDisappear(): void {
@ -58,11 +59,12 @@ export struct ImageKnifeComponent {
this.request.requestState = ImageKnifeRequestState.DESTROY
this.request = undefined
}
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
}
build() {
Image(this.pixelMap)
.objectFit(this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit)
.objectFit(this.objectFit)
.width(this.adaptiveWidth)
.height(this.adaptiveHeight)
.border(this.imageKnifeOption.border)
@ -108,7 +110,7 @@ export struct ImageKnifeComponent {
height,
this.componentVersion,
{
showPixelMap: async (version: number, pixelMap: PixelMap | string) => {
showPixelMap: async (version: number, pixelMap: PixelMap | string, requestSource: ImageKnifeRequestSource) => {
if (version !== this.componentVersion) {
return //针对reuse场景不显示历史图片
}
@ -132,6 +134,17 @@ export struct ImageKnifeComponent {
} else {
//console.info("KKKKKKKKKKK:" + pixelMap)
}
if (requestSource == ImageKnifeRequestSource.SRC) {
this.objectFit =
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
this.objectFit =
this.imageKnifeOption.placeholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.placeholderObjectFit
} else {
this.objectFit =
this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit
}
}
})
}

View File

@ -23,26 +23,16 @@ export interface ImageKnifeData {
imageWidth: number,
imageHeight: number
}
/**
* 读取缓存策略
* 缓存策略
*/
export enum ReadCacheStrategyType {
// 默认-读取内存和文件缓存
export enum CacheStrategy {
// 默认-写入/读取内存和文件缓存
Default = 0,
// 只读取内存缓存
// 只写入/读取内存缓存
Memory = 1,
// 只读取文件缓存
File = 2
}
/**
* 写入缓存策略
*/
export enum WriteCacheStrategyType {
// 默认-写入内存和文件缓存
Default = 0,
// 只写入内存缓存
Memory = 1,
// 只写入文件缓存
// 只写入/读取文件缓存
File = 2
}
@ -82,7 +72,7 @@ export interface RequestJobRequest {
onlyRetrieveFromCache?: boolean
requestSource: ImageKnifeRequestSource
transformation?: PixelMapTransformation
writeCacheStrategy?: WriteCacheStrategyType
writeCacheStrategy?: CacheStrategy
signature?: string
engineKey: IEngineKey
}