加载图片流程添加日志

Signed-off-by: zgf <zenggaofeng2@h-partners.com>
This commit is contained in:
zgf 2024-05-18 18:15:21 +08:00
parent d354a52975
commit 2549d7a8c8
56 changed files with 630 additions and 42 deletions

View File

@ -1,6 +1,9 @@
## 3.0.0-rc.5
- 图片加载事件增加请求开始的回调,以及修复有缓存时没有回调的bug
- 修复对已销毁组件不再下发请求的逻辑
- 加载图片流程添加日志
- 子线程写入文件缓存获取buffer优化
- 成功回调增加返回图片分辨率宽高
## 3.0.0-rc.4
- 支持hsp多包图片资源

View File

@ -7,8 +7,8 @@
{
"name": "default",
"signingConfig": "default",
"compileSdkVersion": "4.1.0(11)",
"compatibleSdkVersion": "4.1.0(11)",
"compileSdkVersion": "5.0.0(12)",
"compatibleSdkVersion": "5.0.0(12)",
"runtimeOS": "HarmonyOS",
}
],
@ -37,6 +37,18 @@
{
"name": "library",
"srcPath": "./library"
},
{
"name": "sharedlibrary",
"srcPath": "./sharedlibrary",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}

View File

@ -6,7 +6,7 @@
"author": "",
"license": "",
"dependencies": {
"@ohos/imageknife": "file:../library"
"@ohos/libraryimageknife": "file:../sharedlibrary",
}
}

View File

@ -12,9 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { IEngineKey, ImageKnifeOption, PixelMapTransformation } from '@ohos/imageknife';
import { SparkMD5 } from '@ohos/imageknife/src/main/ets/3rd_party/sparkmd5/spark-md5';
import { ImageKnifeRequestSource } from '@ohos/imageknife/src/main/ets/model/ImageKnifeData';
import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource} from '@ohos/libraryimageknife';
//全局自定义key demo
@Sendable

View File

@ -17,7 +17,7 @@ import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
import { ImageKnife, LogUtil } from '@ohos/imageknife';
import { ImageKnife, InitImageKnife, LogUtil } from '@ohos/libraryimageknife';
import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl';
export default class EntryAbility extends UIAbility {
@ -35,11 +35,12 @@ export default class EntryAbility extends UIAbility {
LogUtil.mLogLevel = LogUtil.ALL
// 初始化ImageKnife的文件缓存
await ImageKnife.getInstance().initFileCache(this.context, 256, 256 * 1024 * 1024)
await InitImageKnife.init(this.context)
ImageKnife.getInstance().setEngineKeyImpl(new CustomEngineKeyImpl())
// 全局配置请求头
ImageKnife.getInstance().addHeader('refer', "http://1.94.37.200:7070/AntiTheftChain/downloadImage");
ImageKnife.getInstance().deleteHeader('refer');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');

View File

@ -1,6 +1,6 @@
import { BlurTransformation, BrightnessTransformation, ImageKnifeComponent, ImageKnifeOption,
MultiTransTransformation,
PixelMapTransformation } from '@ohos/imageknife'
PixelMapTransformation } from '@ohos/libraryimageknife'
import { collections } from '@kit.ArkTS'
@Entry

View File

@ -26,6 +26,12 @@ struct Index {
build() {
Column() {
Button("测试HSP场景预加载").onClick(()=>{
router.push({
uri: 'pages/TestHspPreLoadImage',
});
})
Button("单个图片使用").onClick(()=>{
router.push({
uri: 'pages/SingleImage',

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife';
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry
@Component

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/imageknife"
import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife"
import matrix4 from '@ohos.matrix4'
@Entry

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent } from '@ohos/imageknife'
import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry
@Component

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent } from '@ohos/imageknife';
import { ImageKnifeComponent } from '@ohos/libraryimageknife';

View File

@ -1,4 +1,4 @@
import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry
@Component

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife';
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent,BlurTransformation } from '@ohos/imageknife';
import { ImageKnifeComponent,BlurTransformation } from '@ohos/libraryimageknife';
import fs from '@ohos.file.fs';
import image from '@ohos.multimedia.image';

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry
@Component

View File

@ -0,0 +1,25 @@
/*
* 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 { IndexComponent } from "@ohos/libraryimageknife"
@Entry
@Component
struct TestHspPreLoadImage {
build() {
Column() {
IndexComponent()
}.width("100%").height('100%')
}
}

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent } from '@ohos/imageknife/src/main/ets/components/ImageKnifeComponent'
import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Observed
export class MsgModel {

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/imageknife'
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife'
@Entry
@Component

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry
@Component

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry
@Component

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/imageknife"
import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife"
import matrix4 from '@ohos.matrix4'

View File

@ -1,4 +1,4 @@
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
// const logger = new imUtils.logger.IMLogger('Avatar')

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -15,6 +15,7 @@
"pages/ImageTransformation",
"pages/ObjectFitPage",
"pages/TestWriteCacheStage",
"pages/LoadStatePage"
"pages/LoadStatePage",
"pages/TestHspPreLoadImage"
]
}

View File

@ -12,7 +12,7 @@ export { LogUtil } from './src/main/ets/utils/LogUtil'
export { IEngineKey } from './src/main/ets/key/IEngineKey'
export { ImageKnifeData , CacheStrategy} from "./src/main/ets/model/ImageKnifeData"
export { ImageKnifeData , CacheStrategy , ImageKnifeRequestSource} from "./src/main/ets/model/ImageKnifeData"
export { PixelMapTransformation } from './src/main/ets/transform/PixelMapTransformation'
@ -22,4 +22,6 @@ export { BrightnessTransformation } from './src/main/ets/transform/BrightnessTra
export { BlurTransformation } from './src/main/ets/transform/BlurTransformation'
export { SparkMD5 } from "./src/main/ets/3rd_party/sparkmd5/spark-md5"

View File

@ -25,6 +25,7 @@ import { FileTypeUtil } from './utils/FileTypeUtil';
import { util } from '@kit.ArkTS';
import { image } from '@kit.ImageKit';
import { common } from '@kit.AbilityKit';
import { LogUtil } from './utils/LogUtil';
export class ImageKnife {
@ -145,6 +146,7 @@ export class ImageKnife {
} else {
imageKnifeOption.loadSrc = loadSrc;
}
LogUtil.log("ImageKnife_DataTime_preLoadCache-imageKnifeOption:"+loadSrc)
let fileKey = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature)
let cachePath = ImageKnife.getInstance().getFileCache().getFileToPath(fileKey)
if (cachePath == null || cachePath == "" || cachePath == undefined) {
@ -299,10 +301,12 @@ export class ImageKnife {
}
async execute(request: ImageKnifeRequest): Promise<void> {
LogUtil.log("ImageKnife_DataTime_execute.start:"+request.imageKnifeOption.loadSrc)
if (this.headerMap.size > 0) {
request.addHeaderMap(this.headerMap)
}
this.dispatcher.enqueue(request)
LogUtil.log("ImageKnife_DataTime_execute.end:"+request.imageKnifeOption.loadSrc)
}
setMaxRequests(concurrency: number): void {

View File

@ -51,6 +51,7 @@ export class ImageKnifeDispatcher {
private engineKey: IEngineKey = new DefaultEngineKey();
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean {
LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:"+request.imageKnifeOption.loadSrc)
let memoryCache: ImageKnifeData | undefined;
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
memoryCache = {
@ -70,22 +71,27 @@ export class ImageKnifeDispatcher {
// 回调请求开始
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
request.imageKnifeOption.onLoadListener?.onLoadStart()
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:"+request.imageKnifeOption.loadSrc)
}
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:"+request.imageKnifeOption.loadSrc)
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, requestSource)
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.end:"+request.imageKnifeOption.loadSrc)
if (requestSource == ImageKnifeRequestSource.SRC) {
request.requestState = ImageKnifeRequestState.COMPLETE
// 回调请求开结束
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
request.imageKnifeOption.onLoadListener?.onLoadSuccess(memoryCache.source)
request.imageKnifeOption.onLoadListener?.onLoadSuccess(memoryCache.source,memoryCache.imageWidth,memoryCache.imageHeight)
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:"+request.imageKnifeOption.loadSrc)
}
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
request.requestState = ImageKnifeRequestState.ERROR
}
}
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_true:"+request.imageKnifeOption.loadSrc)
return true
}
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_false:"+request.imageKnifeOption.loadSrc)
return false
}
@ -106,6 +112,7 @@ export class ImageKnifeDispatcher {
}
executeJob(request: ImageKnifeRequest): void {
LogUtil.log("ImageKnife_DataTime_executeJob.start:"+request.imageKnifeOption.loadSrc)
// 加载占位符
if (request.imageKnifeOption.placeholderSrc !== undefined) {
if (this.showFromMemomry(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER) === false) {
@ -115,12 +122,14 @@ export class ImageKnifeDispatcher {
// 加载主图
this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC)
LogUtil.log("ImageKnife_DataTime_executeJob.end:"+request.imageKnifeOption.loadSrc)
}
/**
* 获取和显示图片
*/
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): void {
LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:"+currentRequest.imageKnifeOption.loadSrc)
let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption)
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
if (requestList == undefined) {
@ -147,7 +156,9 @@ export class ImageKnifeDispatcher {
requestSource
}
// 启动线程下载和解码主图
LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:"+currentRequest.imageKnifeOption.loadSrc)
let task = new taskpool.Task(requestJob, request)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.end:"+currentRequest.imageKnifeOption.loadSrc)
// 监听网络回调事件
if (currentRequest.imageKnifeOption.progressListener !== undefined && requestSource === ImageKnifeRequestSource.SRC) {
let progressCallBack = currentRequest.imageKnifeOption.progressListener
@ -160,11 +171,13 @@ export class ImageKnifeDispatcher {
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart()
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:"+currentRequest.imageKnifeOption.loadSrc)
}
});
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start:"+currentRequest.imageKnifeOption.loadSrc)
taskpool.execute(task).then((res: Object) => {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.start:"+currentRequest.imageKnifeOption.loadSrc)
let requestJobResult = res as RequestJobResult
let pixelmap = requestJobResult === undefined ? undefined : requestJobResult.pixelMap
if (pixelmap === undefined) {
@ -173,6 +186,7 @@ export class ImageKnifeDispatcher {
// 回调请求失败
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined && requestJobResult.loadFail){
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc)
}
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
@ -190,22 +204,24 @@ export class ImageKnifeDispatcher {
}
// 保存文件缓存
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) {
LogUtil.log("ImageKnifeComponent writeCacheStrategy File")
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.start:"+currentRequest.imageKnifeOption.loadSrc)
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc)
}
let ImageKnifeData: ImageKnifeData = {
source: pixelmap!,
imageWidth: 0,
imageHeight: 0
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height
}
// 保存内存缓存
if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) {
LogUtil.log("ImageKnifeComponent writeCacheStrategy Memory")
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc)
ImageKnife.getInstance()
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption),
ImageKnifeData)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
}
if (requestList !== undefined) {
@ -218,15 +234,17 @@ export class ImageKnifeDispatcher {
// 画主图
if (requestWithSource.source === ImageKnifeRequestSource.SRC || requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER && requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc)
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, ImageKnifeData.source, requestWithSource.source)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc)
}
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE
if (requestWithSource.request.imageKnifeOption.onLoadListener && requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
// 回调请求成功
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(ImageKnifeData.source);
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(ImageKnifeData.source,ImageKnifeData.imageWidth,ImageKnifeData.imageHeight);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc)
}
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR
@ -241,12 +259,14 @@ export class ImageKnifeDispatcher {
LogUtil.log("error: no requestlist need to draw for key = " + memoryKey)
}
// })
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.end:"+currentRequest.imageKnifeOption.loadSrc)
});
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
}
dispatchNextJob() {
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.start")
while (true) {
let request = this.jobQueue.pop()
if (request === undefined) {
@ -254,6 +274,7 @@ export class ImageKnifeDispatcher {
}
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
this.executeJob(request)
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end:" + request.imageKnifeOption.loadSrc)
break
}
}
@ -282,6 +303,7 @@ export class ImageKnifeDispatcher {
*/
@Concurrent
async function requestJob(request: RequestJobRequest): Promise<RequestJobResult | undefined> {
LogUtil.log("ImageKnife_DataTime_requestJob.start:"+request.src)
let resBuf: ArrayBuffer | undefined
let bufferSize: number = 0
let loadError: string = '';
@ -315,6 +337,7 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
// 先从文件缓存获取
resBuf = FileCache.getFileCacheByFile(request.context, fileKey)
if (resBuf === undefined && request.onlyRetrieveFromCache != true) {
LogUtil.log("ImageKnife_DataTime_requestJob_httpRequest.start:"+request.src)
let httpRequest = http.createHttp();
let progress: number = 0
let arrayBuffers = new Array<ArrayBuffer>()
@ -359,12 +382,14 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
loadError = err.message;
LogUtil.error("requestInStream ERROR : err = " + JSON.stringify(err));
});
LogUtil.log("ImageKnife_DataTime_requestJob_httpRequest.end:"+request.src)
// 保存文件缓存
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug不能直接获取resBuf.byteLength
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
let copyBuf = combineArrayBuffers(arrayBuffers); // IDE有bug不能直接获取resBuf.byteLength
bufferSize = copyBuf.byteLength
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf)
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
}
}
else {
@ -406,6 +431,7 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
if (resBuf == undefined) {
LogUtil.log("ImageKnife_DataTime_requestJob.end_undefined:"+request.src)
return {
pixelMap: undefined,
bufferSize: 0,
@ -413,13 +439,15 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
loadFail: loadError,
}
}
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.start:"+request.src)
let fileTypeUtil = new FileTypeUtil();
let typeValue = fileTypeUtil.getFileType(resBuf);
if (typeValue === 'gif' || typeValue === 'webp') {
let base64Help = new util.Base64Helper()
let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(resBuf))
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end_GIF:"+request.src)
LogUtil.log("ImageKnife_DataTime_requestJob.end_GIF:"+request.src)
return {
pixelMap: base64str,
bufferSize: bufferSize,
@ -433,6 +461,7 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
}
let resPixelmap: PixelMap | undefined = undefined
let size = (await imageSource.getImageInfo()).size
await imageSource.createPixelMap(decodingOptions)
.then((pixelmap: PixelMap) => {
resPixelmap = pixelmap
@ -443,11 +472,13 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined) {
resPixelmap = await request.transformation?.transform(request.context, resPixelmap!, 0, 0)
}
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end:"+request.src)
LogUtil.log("ImageKnife_DataTime_requestJob.end:"+request.src)
return {
pixelMap: resPixelmap,
bufferSize: bufferSize,
fileKey: fileKey
fileKey: fileKey,
size:size
};
}

View File

@ -73,7 +73,7 @@ export interface OnLoadCallBack {
// 请求开始
onLoadStart?: () => void;
// 请求成功
onLoadSuccess?: (data: string | PixelMap | undefined) => void;
onLoadSuccess?: (data: string | PixelMap | undefined,width?:number,height?:number) => void;
// 请求结束
onLoadFailed?: (err: string) => void;
}

View File

@ -17,6 +17,7 @@ import { ImageKnifeRequest } from '../ImageKnifeRequest'
import { IEngineKey } from '../key/IEngineKey'
import { PixelMapTransformation } from '../transform/PixelMapTransformation'
import common from '@ohos.app.ability.common';
import { Size } from '@kit.ArkUI'
export interface ImageKnifeData {
source: PixelMap | string,
@ -59,6 +60,7 @@ export interface RequestJobResult {
bufferSize: number
fileKey: string
loadFail?: string,
size?:Size
}
/**

View File

@ -108,6 +108,7 @@ export class MemoryLruCache implements IMemoryCache {
this.currentMemory -= value.source.length
} else {
this.currentMemory -= value.source.getPixelBytesNumber();
value.source.release()
}
// LogUtil.info("MemoryCache removeMemorySize: " + value.source.getPixelBytesNumber() + " currentMemory" + this.currentMemory)
}

6
sharedlibrary/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

33
sharedlibrary/Index.ets Normal file
View File

@ -0,0 +1,33 @@
export { add } from './src/main/ets/utils/Calc'
export { InitImageKnife } from "./src/main/ets/pages/InitImageKnife"
export { IndexComponent } from "./src/main/ets/pages/Index"
export { ImageKnifeComponent } from '@ohos/imageknife'
export { ImageKnife } from '@ohos/imageknife'
export { ImageKnifeOption } from '@ohos/imageknife'
export { ImageKnifeRequest } from '@ohos/imageknife'
export { FileUtils } from '@ohos/imageknife'
export { LogUtil } from '@ohos/imageknife'
export { IEngineKey } from '@ohos/imageknife'
export { ImageKnifeData , CacheStrategy} from "@ohos/imageknife"
export { PixelMapTransformation } from '@ohos/imageknife'
export { MultiTransTransformation } from '@ohos/imageknife'
export { BrightnessTransformation } from '@ohos/imageknife'
export { BlurTransformation } from '@ohos/imageknife'
export { SparkMD5 } from "@ohos/imageknife"
export { ImageKnifeRequestSource } from "@ohos/imageknife"

View File

@ -0,0 +1,28 @@
{
"apiType": "stageMode",
"buildOption": {
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
}
}
},
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest"
}
]
}

View File

@ -0,0 +1,6 @@
import { hspTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hspTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

View File

@ -0,0 +1,18 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope

View File

@ -0,0 +1,12 @@
{
"name": "sharedlibrary",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "Index.ets",
"author": "",
"license": "Apache-2.0",
"packageType": "InterfaceHar",
"dependencies": {
"@ohos/imageknife": "file:../library"
}
}

View File

@ -0,0 +1,39 @@
/*
* 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 { ImageKnife , ImageKnifeComponent ,ImageKnifeOption } from "@ohos/imageknife"
@Component
export struct IndexComponent {
@State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon')
}
build() {
Column() {
Button("预加载").onClick((event: ClickEvent) => {
ImageKnife.getInstance()
.preLoadCache('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp')
.then((data) => {
console.log("preLoadImage_FileCache:" + data)
this.imageKnifeOption.loadSrc = data
})
})
ImageKnifeComponent({
imageKnifeOption:this.imageKnifeOption
}).width(300).height(300)
}
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,21 @@
/*
* 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 { ImageKnife } from '@ohos/imageknife'
import common from '@ohos.app.ability.common'
export class InitImageKnife{
static async init(entryContext:common.UIAbilityContext){
await ImageKnife.getInstance().initFileCache(entryContext, 256, 256 * 1024 * 1024)
}
}

View File

@ -0,0 +1,3 @@
export function add(a:number, b:number) {
return a + b;
}

View File

@ -0,0 +1,14 @@
{
"module": {
"name": "sharedlibrary",
"type": "shared",
"description": "$string:shared_desc",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"pages": "$profile:main_pages"
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "white",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "shared_desc",
"value": "description"
}
]
}

View File

@ -0,0 +1,5 @@
{
"src": [
"pages/Index"
]
}

View File

@ -0,0 +1,2 @@
{
}

View File

@ -0,0 +1,35 @@
import { hilog } from '@kit.PerformanceAnalysisKit';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function abilityTest() {
describe('ActsAbilityTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
})
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
})
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
})
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
})
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
})
})
}

View File

@ -0,0 +1,5 @@
import abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}

View File

@ -0,0 +1,47 @@
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { abilityDelegatorRegistry } from '@kit.TestKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { Hypium } from '@ohos/hypium';
import testsuite from '../test/List.test';
export default class TestAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator();
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments();
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
windowStage.loadContent('testability/pages/Index', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
}
onForeground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
}
onBackground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
}
}

View File

@ -0,0 +1,17 @@
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}

View File

@ -0,0 +1,90 @@
import { abilityDelegatorRegistry, TestRunner } from '@kit.TestKit';
import { UIAbility, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { resourceManager } from '@kit.LocalizationKit';
import { util } from '@kit.ArkTS';
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
let jsonPath: string = 'mock/mock-config.json';
let tag: string = 'testTag';
async function onAbilityCreateCallback(data: UIAbility) {
hilog.info(0x0000, 'testTag', 'onAbilityCreateCallback, data: ${}', JSON.stringify(data));
}
async function addAbilityMonitorCallback(err: BusinessError) {
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare');
}
async onRun() {
let tag = 'testTag';
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments()
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
let moduleName = abilityDelegatorArguments.parameters['-m'];
let context = abilityDelegator.getAppContext().getApplicationContext().createModuleContext(moduleName);
let mResourceManager = context.resourceManager;
await checkMock(abilityDelegator, mResourceManager);
const bundleName = abilityDelegatorArguments.bundleName;
const testAbilityName: string = 'TestAbility';
let lMonitor: abilityDelegatorRegistry.AbilityMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
moduleName: moduleName
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
const want: Want = {
bundleName: bundleName,
abilityName: testAbilityName,
moduleName: moduleName
};
abilityDelegator.startAbility(want, (err: BusinessError, data: void) => {
hilog.info(0x0000, tag, 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, tag, 'startAbility : data : %{public}s', JSON.stringify(data) ?? '');
})
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}
async function checkMock(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator, resourceManager: resourceManager.ResourceManager) {
let rawFile: Uint8Array;
try {
rawFile = resourceManager.getRawFileContentSync(jsonPath);
hilog.info(0x0000, tag, 'MockList file exists');
let mockStr: string = util.TextDecoder.create('utf-8', { ignoreBOM: true }).decodeWithStream(rawFile);
let mockMap: Record<string, string> = getMockList(mockStr);
try {
abilityDelegator.setMockList(mockMap)
} catch (error) {
let code = (error as BusinessError).code;
let message = (error as BusinessError).message;
hilog.error(0x0000, tag, `abilityDelegator.setMockList failed, error code: ${code}, message: ${message}.`);
}
} catch (error) {
let code = (error as BusinessError).code;
let message = (error as BusinessError).message;
hilog.error(0x0000, tag, `ResourceManager:callback getRawFileContent failed, error code: ${code}, message: ${message}.`);
}
}
function getMockList(jsonStr: string) {
let jsonObj: Record<string, Object> = JSON.parse(jsonStr);
let map: Map<string, object> = new Map<string, object>(Object.entries(jsonObj));
let mockList: Record<string, string> = {};
map.forEach((value: object, key: string) => {
let realValue: string = value['source'].toString();
mockList[key] = realValue;
});
hilog.info(0x0000, tag, '%{public}s', 'mock-json value:' + JSON.stringify(mockList) ?? '');
return mockList;
}

View File

@ -0,0 +1,38 @@
{
"module": {
"name": "sharedlibrary_test",
"type": "feature",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:test_pages",
"abilities": [
{
"name": "TestAbility",
"srcEntry": "./ets/testability/TestAbility.ets",
"description": "$string:TestAbility_desc",
"icon": "$media:icon",
"label": "$string:TestAbility_label",
"exported": true,
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
]
}
]
}
]
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,5 @@
{
"src": [
"testability/pages/Index"
]
}

View File

@ -0,0 +1,5 @@
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}

View File

@ -0,0 +1,33 @@
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function localUnitTest() {
describe('localUnitTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
});
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
});
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
});
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
});
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
});
});
}