diff --git a/CHANGELOG.md b/CHANGELOG.md index 262ece6..1b3e88c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ - 修改ImageKnife跳过网络,从内存中获取图片 cacheType参数未使用bug - 新增WEBP图片解析能力。 - 新增gif图片支持暂停播放功能 +- 修复自定义DataFetch接口实现不生效问题 +- 修改磁盘缓存到子线程 +- 更新SDK到API12 +- 适配Sendable内存共享优化 ## 2.1.2-rc.12 - 新增gif播放次数功能 @@ -10,7 +14,6 @@ - 删除多余操作磁盘记录读写 - 清除定时器改为Gif图时清除 - uuid改为util.generateRandomUUID() -- 修改ImageKnife跳过网络,从内存中获取图片 cacheType参数未使用bug ## 2.1.2-rc.11 - 修复设置磁盘容量最大值出现闪退 diff --git a/README.md b/README.md index 7e852c6..459a5c3 100644 --- a/README.md +++ b/README.md @@ -460,6 +460,10 @@ HSP场景适配: 非HSP场景不影响原功能, ImageKnifeOption配置类新增的可选参数context可以不传, RquestOption配置类新增的接口可以不调用。 +注意: + +基于性能优化的原因,2.1.2-rc.13及以后版本引用了API12 Sendable接口,至此以后的版本只支持API12。 + ## 目录结构 ``` diff --git a/build-profile.json5 b/build-profile.json5 index aa57008..79fdb01 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -4,8 +4,8 @@ { "name": "default", "signingConfig": "default", - "compileSdkVersion": 10, - "compatibleSdkVersion": 10 + "compileSdkVersion": 12, + "compatibleSdkVersion": 12 } ], "buildModeSet": [ diff --git a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets index 498d585..752763f 100644 --- a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets +++ b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets @@ -363,6 +363,10 @@ struct IndexFunctionDemo { .onClick(() => { router.pushUrl({ url: 'pages/testImageKnifeHttpRequestHeader' }); }).margin({ top: 5, left: 3 }) + Button('测试自定义DataFetch属性') + .onClick(() => { + router.pushUrl({ url: 'pages/testImageKnifeDataFetch' }); + }).margin({ top: 5, left: 3 }) }.width('100%').height(60).backgroundColor(Color.Pink) Text('测试图片缓存内存').fontSize(15) diff --git a/entry/src/main/ets/pages/testImageKnifeDataFetch.ets b/entry/src/main/ets/pages/testImageKnifeDataFetch.ets new file mode 100644 index 0000000..c097e9d --- /dev/null +++ b/entry/src/main/ets/pages/testImageKnifeDataFetch.ets @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2023 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 { + Base64, + IDataFetch, + ImageKnife, + ImageKnifeComponent, + ImageKnifeGlobal, + ImageKnifeOption, + DataFetchResult, + RequestOption} from '@ohos/libraryimageknife' +import common from '@ohos.app.ability.common'; +import resourceManager from '@ohos.resourceManager'; +import { BusinessError } from '@ohos.base' + +@Entry +@Component +struct TestImageKnifeDataFetch { + + @State imageKnifeOption1: ImageKnifeOption = + { + loadSrc: $r('app.media.icon'), + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + }; + + build() { + Column(){ + Text("简单示例1:加载一张本地png图片").fontSize(15) + Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Button("加载PNG") + .onClick(() => { + let dataFetch:MyDataFetch = new MyDataFetch(); + let imageKnife:ImageKnife|undefined = ImageKnifeGlobal.getInstance().getImageKnife() + if(imageKnife != undefined) { + imageKnife.replaceDataFetch(dataFetch) + } + this.imageKnifeOption1 = { + loadSrc: "", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + isCacheable: false, + } + }).margin({ top: 5, left: 3 }) + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) + }.width('100%').backgroundColor(Color.Pink) + } + } + +} + +@Sendable +class MyDataFetch implements IDataFetch{ + loadData(option: RequestOption) { + let result:DataFetchResult = new DataFetchResult(); + ((ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext).resourceManager as resourceManager.ResourceManager) + .getMediaContentBase64($r('app.media.pngSample').id) + .then(data => { + let matchReg = ';base64,'; + let firstIndex = data.indexOf(matchReg); + data = data.substring(firstIndex + matchReg.length, data.length) + console.log('MyDataFetch - 本地加载资源 解析后数据剔除非必要数据后data= ' + data) + let arrayBuffer = Base64.getInstance() + .decode(data); + result.data = arrayBuffer; + }).catch((err:BusinessError) => { + result.error = 'MyDataFetch - 本地加载资源err' + JSON.stringify(err); + }) + return result; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/testManyNetImageLoadWithPage2.ets b/entry/src/main/ets/pages/testManyNetImageLoadWithPage2.ets index ee0c3d0..ad927d8 100644 --- a/entry/src/main/ets/pages/testManyNetImageLoadWithPage2.ets +++ b/entry/src/main/ets/pages/testManyNetImageLoadWithPage2.ets @@ -51,13 +51,13 @@ struct TestManyNetImageLoadWithPage2 { .backgroundColor(Color.Orange) } }.width('45%').height(200) - }, (item: Material) => item.material_id) + }, (item: Material,index:number) => item.material_id + index.toString()) } .columnsTemplate('1fr 1fr') .columnsGap(8) .rowsGap(10) .width('100%') - .cachedCount(1) + .cachedCount(3) .height('100%') }.margin({ top: 5 }) } diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index e33f091..d5bfffb 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -22,7 +22,7 @@ "abilities": [ { "name": "MainAbility", - "srcEntrance": "./ets/entryability/EntryAbility.ets", + "srcEntry": "./ets/entryability/EntryAbility.ets", "description": "$string:MainAbility_desc", "icon": "$media:icon", "label": "$string:MainAbility_label", diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index b79794a..295016b 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -50,6 +50,7 @@ "pages/testReusePhotoPage", "pages/testImageKnifeCache", "pages/webpImageTestPage", - "pages/testStopPlayingGifPage" + "pages/testStopPlayingGifPage", + "pages/testImageKnifeDataFetch" ] } \ No newline at end of file diff --git a/library/index.ets b/library/index.ets index c6b4405..f25c784 100644 --- a/library/index.ets +++ b/library/index.ets @@ -31,6 +31,7 @@ export { NONE } from './src/main/ets/components/cache/diskstrategy/enum/NONE' export { RESOURCE } from './src/main/ets/components/cache/diskstrategy/enum/RESOURCE' export { EngineKeyInterface } from './src/main/ets/components/cache/key/EngineKeyInterface' export { EngineKeyFactories } from './src/main/ets/components/cache/key/EngineKeyFactories' +export { DataFetchResult } from './src/main/ets/components/imageknife/networkmanage/DataFetchResult' /** * compress diff --git a/library/src/main/ets/components/cache/CustomSendableMap.ets b/library/src/main/ets/components/cache/CustomSendableMap.ets new file mode 100644 index 0000000..bb33b65 --- /dev/null +++ b/library/src/main/ets/components/cache/CustomSendableMap.ets @@ -0,0 +1,88 @@ +/* + * 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. + */ +import { collections } from '@kit.ArkTS' +import { DiskCacheEntry } from './DiskCacheEntry'; + +@Sendable +export class CustomSendableMap { + map: collections.Map = new collections.Map() + + // 获取键对应的值 + get(key: string): DiskCacheEntry | undefined{ + if (key == null) { + throw new Error('key is null,checking the parameter'); + } + return this.map.get(key) + } + + /** + * 是否含有key的缓存 + */ + hasKey(key: string):boolean { + if (key == null) { + throw new Error('key is null,checking the parameter'); + } + return this.map.has(key) + } + + // 添加键值对 + put(key: string, value: DiskCacheEntry): DiskCacheEntry | undefined{ + if (key == null || value == null) { + throw new Error('key or value is invalid,checking the parameter'); + } + let pre = this.map.get(key) as DiskCacheEntry | undefined; + if (this.hasKey(key)) { + this.map.delete(key) + } + this.map.set(key, value); + return pre + } + + // 去除键值,(去除键数据中的键名及对应的值) + remove(key: string): boolean { + if (key == null) { + throw new Error('key is null,checking the parameter'); + } + return this.map.delete(key) + } + + /** + * 获取最先存储的数据的key + */ + getFirstKey(): string{ // keys()可以遍历后需要优化put()方法,暂时仅获取index=0的key + return this.map.keys().next().value + } + + // 判断键值元素是否为空 + isEmpty(): boolean{ + return this.map.size == 0; + } + // 获取键值元素大小 + size(): number{ + return this.map.size; + } + // 遍历Map,执行处理函数. 回调函数 function(key,value,index){..} + each(fn: (value: DiskCacheEntry, key: string, map: collections.Map) => void) { + this.map.forEach(fn) + } + // 清除键值对 + clear() { + this.map.clear() + } + // 遍历key + keys(): IterableIterator{ + return this.map.keys() + } +} \ No newline at end of file diff --git a/library/src/main/ets/components/cache/DiskCacheEntry.ets b/library/src/main/ets/components/cache/DiskCacheEntry.ets index 959f12f..c52cd4f 100644 --- a/library/src/main/ets/components/cache/DiskCacheEntry.ets +++ b/library/src/main/ets/components/cache/DiskCacheEntry.ets @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@Sendable export class DiskCacheEntry { // 缓存的key key: string = '' diff --git a/library/src/main/ets/components/cache/DiskLruCache.ets b/library/src/main/ets/components/cache/DiskLruCache.ets index 7bc9521..198bc5f 100644 --- a/library/src/main/ets/components/cache/DiskLruCache.ets +++ b/library/src/main/ets/components/cache/DiskLruCache.ets @@ -12,12 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CustomMap } from './CustomMap' import { FileUtils } from './FileUtils' import { DiskCacheEntry } from './DiskCacheEntry' import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5' import common from '@ohos.app.ability.common' +import { CustomSendableMap } from './CustomSendableMap' +@Sendable export class DiskLruCache { // 默认缓存数据最大值 private static readonly DEFAULT_MAX_SIZE: number = 300 * 1024 * 1024 @@ -25,16 +26,13 @@ export class DiskLruCache { private static readonly DEFAULT_NAME: string = 'diskLruCache' // 缓存文件路径地址 private path: string = '' - // 缓存journal文件路径 - private journalPath: string = '' - // 缓存journal备份文件路径 - private journalPathTemp: string = '' + // 缓存数据最大值 private maxSize: number = DiskLruCache.DEFAULT_MAX_SIZE // 当前缓存数据值 private size: number = 0 // 缓存数据集合 - private cacheMap: CustomMap = new CustomMap() + private cacheMap: CustomSendableMap = new CustomSendableMap() constructor(path: string, maxSize: number) { this.path = path @@ -271,7 +269,6 @@ export class DiskLruCache { this.cacheMap.each((value, key) => { FileUtils.getInstance().deleteFile(this.path + key) }) - FileUtils.getInstance().deleteFile(this.journalPath) this.cacheMap.clear() this.size = 0 } @@ -382,7 +379,6 @@ export class DiskLruCache { } if (this.fileSizeMoreThenMaxSize(fileSize)) { throw new Error('content must be less then DiskLruCache Size, checking the parameter') - return } key = SparkMD5.hashBinary(key); this.size = this.size + fileSize; diff --git a/library/src/main/ets/components/imageknife/ImageKnife.ets b/library/src/main/ets/components/imageknife/ImageKnife.ets index 0f70822..4e0ba52 100644 --- a/library/src/main/ets/components/imageknife/ImageKnife.ets +++ b/library/src/main/ets/components/imageknife/ImageKnife.ets @@ -31,6 +31,7 @@ import { IResourceFetch } from '../imageknife/resourcemanage/IResourceFetch' import { ImageKnifeData, ImageKnifeType } from '../imageknife/ImageKnifeData' import { ImageKnifeGlobal } from '../imageknife/ImageKnifeGlobal' import image from "@ohos.multimedia.image" +import http from '@ohos.net.http' import { CompressBuilder } from "../imageknife/compress/CompressBuilder" import { IDrawLifeCycle } from '../imageknife/interface/IDrawLifeCycle' import { LogUtil } from '../imageknife/utils/LogUtil' @@ -46,13 +47,16 @@ import emitter from '@ohos.events.emitter'; import { MemoryCacheProxy } from './requestmanage/MemoryCacheProxy' import { ObjectKey } from './ObjectKey' -import { TaskParams } from './TaskParams' import { Constants } from './constants/Constants' import { TransformUtils } from './transform/TransformUtils' import { GIFParseImpl } from './utils/gif/GIFParseImpl' import { IParseImage } from './interface/IParseImage' import { ParseImageUtil } from './utils/ParseImageUtil' import { SVGParseImpl } from './utils/svg/SVGParseImpl' +import { SendableData } from './SendableData' +import { collections } from '@kit.ArkTS' +import { TaskParams } from './TaskParams' +import { MResource } from './utils/MResource' export class ImageKnife { static readonly SEPARATOR: string = '/' @@ -374,7 +378,7 @@ export class ImageKnife { } loadMemoryDiskIsUrl(request: RequestOption, onComplete: (imageKnifeData: ImageKnifeData) => void | PromiseLike, onError: (err?: BusinessError | string) => void) { - let cached: ArrayBuffer = DiskLruCache.getFileCacheByFile(this.diskMemoryCache.getPath() as string, request.generateDataKey) as ArrayBuffer; + let cached = this.diskMemoryCache.get(request.generateDataKey); if (cached != null) { let filetype: string | null = this.fileTypeUtil.getFileType(cached); @@ -625,39 +629,67 @@ export class ImageKnife { } } - //组装任务参数 - private assembleTaskParams(request: RequestOption, usageType: string) { + private assembleSendableData(request: RequestOption, usageType: string){ //图片变换方法无法直接传递到子线程,这里先把对象名和构造参数传递到子线程,然后在子线程中实例化变换方法 - let transformations: string [][] = []; + + let transformations: collections.Array> = new collections.Array>(); + if (usageType == Constants.MAIN_HOLDER) { for (let i = 0; i < request.transformations.length; i++) { - transformations.push([request.transformations[i].getClassName(), request.transformations[i].getConstructorParams()]) + let item = collections.Array.from([request.transformations[i].getClassName(), request.transformations[i].getConstructorParams()]) as collections.Array; + transformations.push(item) } } let displayProgress = request.progressFunc ? true : false; - //將要传递到子线程的参数,放在一个json对象上,避免方法参数过多 - let taskParams: TaskParams = { + + let data: SendableData = new SendableData(); + data.setUsageType(usageType) + data.setDisplayProgress(displayProgress) + data.setUuid(request.uuid) + data.setDontAnimateFlag(request.dontAnimateFlag) + data.setThumbSizeMultiplier(request.thumbSizeMultiplier) + data.setThumbDelayTime(request.thumbDelayTime) + data.setOnlyRetrieveFromCache(request.onlyRetrieveFromCache) + data.setIsCacheable(request.isCacheable) + data.setGpuEnabled(request.gpuEnabled) + data.setGenerateCacheKey(request.generateCacheKey) + data.setGenerateResourceKey(request.generateResourceKey) + data.setGenerateDataKey(request.generateDataKey) + data.setSignature(request.signature) + data.setTransformations(transformations) + data.setDiskMemoryCache(this.diskMemoryCache) + data.setDataFetch(this.dataFetch) + data.setDiskMemoryCachePath(this.diskMemoryCache.getPath()) + return data; + } + + private assembleSTaskData(request: RequestOption){ + let data: TaskParams = { headers: request.headers, moduleContext: request.moduleContext, - transformations: transformations, - usageType: usageType, - displayProgress: displayProgress, - uuid: request.uuid, - dontAnimateFlag: request.dontAnimateFlag, priority: request.priority, - generateCacheKey: request.generateCacheKey, - generateResourceKey: request.generateResourceKey, - generateDataKey: request.generateDataKey, - thumbSizeMultiplier: request.thumbSizeMultiplier, - thumbDelayTime: request.thumbDelayTime, size: request.size, - onlyRetrieveFromCache: request.onlyRetrieveFromCache, - gpuEnabled: request.gpuEnabled, - signature: request.signature, - isCacheable: request.isCacheable, - diskMemoryCachePath: this.diskMemoryCache.getPath() + loadSrc: this.transformResource(request.loadSrc) as string | PixelMap | MResource, + placeholderSrc: this.transformResource(request.placeholderSrc) as PixelMap | MResource | undefined, + errorholderSrc: this.transformResource(request.errorholderSrc) as PixelMap | MResource | undefined, + retryholderSrc:this.transformResource(request.retryholderSrc) as PixelMap | MResource | undefined } - return taskParams; + return data; + } + + private transformResource(loadSrc:string | PixelMap | Resource | undefined):string | PixelMap | MResource | undefined{ + let res = loadSrc as Resource + if (res && res.id && res.type) { + return { + bundleName: res.bundleName, + moduleName: res.moduleName, + id: res.id, + params: res.params, + type: res.type + } as MResource; + } + return loadSrc as string | PixelMap | undefined; + } //多线程请求加载资源 @@ -685,24 +717,21 @@ export class ImageKnife { request.loadComplete(mainCache); return; } + //组装可以通过sendable传递的数据 + let sendData:SendableData = this.assembleSendableData(request, usageType); + //其他不能sendable发送的数据 + let taskData:TaskParams = this.assembleSTaskData(request); - let taskParams: TaskParams = this.assembleTaskParams(request, usageType); - let loadSrcJson = JSON.stringify({ - loadSrc: request.loadSrc, - placeholderSrc: request.placeholderSrc, - errorholderSrc: request.errorholderSrc, - retryholderSrc: request.retryholderSrc, - }); //使用taskpool多线程执行资源下载 - let task: ESObject = new taskpool.Task(taskExecute, taskParams, loadSrcJson) - task.setTransferList([]) - - emitter.on(Constants.PROGRESS_EMITTER as ESObject, (data: ESObject) => { - if (request.progressFunc && data?.data?.value) { - let percent = data.data.value as number; - request.progressFunc.asyncSuccess(percent); - } - }); + let task: ESObject = new taskpool.Task(taskExecute,sendData,taskData) + if (request.progressFunc){ + emitter.on(Constants.PROGRESS_EMITTER as ESObject, (data: ESObject) => { + if (request.progressFunc && data?.data?.value) { + let percent = data.data.value as number; + request.progressFunc.asyncSuccess(percent); + } + }); + } taskpool.execute(task,request.priority).then((data: ESObject) => { if (usageType == Constants.PLACE_HOLDER) { if ((typeof (data as PixelMap).isEditable) == 'boolean') { @@ -733,12 +762,10 @@ export class ImageKnife { let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap); request.loadComplete(imageKnifeData) this.memoryCacheProxy.putValue(request.generateCacheKey,imageKnifeData) - this.setDiskCache(request) } else if ((data as GIFFrame[]).length > 0) { let imageKnifeData = ImageKnifeData.createImageGIFFrame(ImageKnifeType.GIFFRAME, data as GIFFrame[]); request.loadComplete(imageKnifeData) this.memoryCacheProxy.putValue(request.generateCacheKey,imageKnifeData) - this.setDiskCache(request) } else { request.loadError("request resources error") } @@ -749,25 +776,6 @@ export class ImageKnife { } - private setDiskCache(request: RequestOption):void{ - try { - // let diskMemoryCache = ImageKnifeGlobal.getInstance().getImageKnife()?.getDiskMemoryCache(); - let dataArraybuffer: ArrayBuffer = DiskLruCache.getFileCacheByFile(this.diskMemoryCache.getPath() as string, request.generateDataKey) as ArrayBuffer; - //缓存原图片 - if (dataArraybuffer) { - this.diskMemoryCache.setCacheMapAndSize(request.generateDataKey, dataArraybuffer); - } - //缓存变换后图片 - let resourceArraybuffer: ArrayBuffer = DiskLruCache.getFileCacheByFile(this.diskMemoryCache.getPath() as string, request.generateResourceKey) as ArrayBuffer; - if (resourceArraybuffer) { - this.diskMemoryCache.setCacheMapAndSize(request.generateResourceKey, resourceArraybuffer); - } - - } catch (e) { - LogUtil.error("imageknife DiskMemoryCache setDiskCache error :" + e.message); - } - } - private keyNotEmpty(request: RequestOption): boolean { if ( request.generateCacheKey != null && request.generateCacheKey.length > 0 && @@ -868,7 +876,10 @@ export class ImageKnife { * @returns */ @Concurrent -async function taskExecute(taskParams: TaskParams, loadSrcJson: string): Promise { +async function taskExecute(sendData:SendableData,taskData:TaskParams): Promise { + + //sendable里面加载http模块有问题,需要在@Concurrent先使用下,临时规避方法,待Sendable解决后删除 + let unused_arg0 = http.CertType; let emitProgressPercent = (percentValue: number) => { let eventData: emitter.EventData = { @@ -879,34 +890,40 @@ async function taskExecute(taskParams: TaskParams, loadSrcJson: string): Promise emitter.emit(Constants.PROGRESS_EMITTER as ESObject, eventData) } - let transformations = taskParams.transformations; - let usageType = taskParams.usageType; - let displayProgress = taskParams.displayProgress; + let transformations = sendData.getTransformations(); + let usageType = sendData.getUsageType(); + let displayProgress = sendData.getDisplayProgress(); //子线程构造RequestOption对象 let newRequestOption = new RequestOption(); - let loadSrcObj: object = JSON.parse(loadSrcJson); - newRequestOption.priority = taskParams.priority - newRequestOption.uuid = taskParams.uuid; - newRequestOption.loadSrc = loadSrcObj["loadSrc"] as string | PixelMap | Resource; - newRequestOption.dontAnimateFlag = taskParams.dontAnimateFlag; - newRequestOption.generateCacheKey = taskParams.generateCacheKey; - newRequestOption.generateResourceKey = taskParams.generateResourceKey; - newRequestOption.generateDataKey = taskParams.generateDataKey; - newRequestOption.thumbSizeMultiplier = taskParams.thumbSizeMultiplier; - newRequestOption.thumbDelayTime = taskParams.thumbDelayTime; - newRequestOption.size = taskParams.size; - newRequestOption.diskMemoryCachePath = taskParams.diskMemoryCachePath; - newRequestOption.placeholderSrc = loadSrcObj["placeholderSrc"] as PixelMap | Resource | undefined; - newRequestOption.errorholderSrc = loadSrcObj["errorholderSrc"] as PixelMap | Resource | undefined; - newRequestOption.retryholderSrc = loadSrcObj["retryholderSrc"] as PixelMap | Resource | undefined; - newRequestOption.onlyRetrieveFromCache = taskParams.onlyRetrieveFromCache; - newRequestOption.gpuEnabled = taskParams.gpuEnabled; - newRequestOption.headers = taskParams.headers; - newRequestOption.signature = taskParams.signature; - ImageKnifeGlobal.getInstance().setHapContext(taskParams.moduleContext as common.UIAbilityContext); - newRequestOption.moduleContext = taskParams.moduleContext; - newRequestOption.isCacheable = taskParams.isCacheable; + newRequestOption.priority = taskData.priority; + newRequestOption.uuid = sendData.getUuid(); + newRequestOption.loadSrc = taskData.loadSrc as string | PixelMap | Resource; + newRequestOption.dontAnimateFlag = sendData.getDontAnimateFlag(); + newRequestOption.generateCacheKey = sendData.getGenerateCacheKey(); + newRequestOption.generateResourceKey = sendData.getGenerateResourceKey(); + newRequestOption.generateDataKey = sendData.getGenerateDataKey(); + newRequestOption.thumbSizeMultiplier = sendData.getThumbSizeMultiplier(); + newRequestOption.thumbDelayTime = sendData.getThumbDelayTime(); + newRequestOption.size = taskData.size; + if(taskData.loadSrc){ + newRequestOption.placeholderSrc = taskData.loadSrc as PixelMap | Resource | undefined; + } + if(taskData.errorholderSrc){ + newRequestOption.errorholderSrc = taskData.errorholderSrc as PixelMap | Resource | undefined; + } + if(taskData.retryholderSrc){ + newRequestOption.retryholderSrc = taskData.retryholderSrc as PixelMap | Resource | undefined; + } + newRequestOption.onlyRetrieveFromCache = sendData.getOnlyRetrieveFromCache(); + newRequestOption.gpuEnabled = sendData.getGpuEnabled(); + newRequestOption.headers = taskData.headers; + newRequestOption.signature = sendData.getSignature(); + ImageKnifeGlobal.getInstance().setHapContext(taskData.moduleContext as common.UIAbilityContext); + newRequestOption.moduleContext = taskData.moduleContext as common.UIAbilityContext; + newRequestOption.isCacheable = sendData.getIsCacheable(); + //设置磁盘缓存路径 + newRequestOption.diskMemoryCachePath = sendData.getDiskMemoryCachePath(); if (displayProgress) { newRequestOption.addProgressListener({ asyncSuccess: (percentValue: number) => { @@ -934,9 +951,10 @@ async function taskExecute(taskParams: TaskParams, loadSrcJson: string): Promise if (transformations) { newRequestOption.setTransformations(TransformUtils.addTransformations(transformations)) } - let newDataFetch = new DownloadClient(); + let diskMemoryCache = sendData.getDiskMemoryCache(); + let newDataFetch = sendData.getDataFetch(); let newResourceFetch = new ParseResClient(); - let manager = new RequestManager(newRequestOption, newDataFetch, newResourceFetch); + let manager = new RequestManager(newRequestOption, diskMemoryCache as DiskLruCache, newDataFetch, newResourceFetch); return await new Promise(manager.process); } } diff --git a/library/src/main/ets/components/imageknife/ObjectKey.ets b/library/src/main/ets/components/imageknife/ObjectKey.ets index 9a121ae..18108f7 100644 --- a/library/src/main/ets/components/imageknife/ObjectKey.ets +++ b/library/src/main/ets/components/imageknife/ObjectKey.ets @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@Sendable export class ObjectKey{ private objectKey: string; diff --git a/library/src/main/ets/components/imageknife/SendableData.ets b/library/src/main/ets/components/imageknife/SendableData.ets new file mode 100644 index 0000000..e91be08 --- /dev/null +++ b/library/src/main/ets/components/imageknife/SendableData.ets @@ -0,0 +1,179 @@ +/* + * 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 { ObjectKey } from './ObjectKey'; +import common from '@ohos.app.ability.common' +import { collections } from '@kit.ArkTS'; +import { IDataFetch } from './networkmanage/IDataFetch'; +import { DiskLruCache } from '../cache/DiskLruCache'; +import { DownloadClient } from './networkmanage/DownloadClient'; + +@Sendable +export class SendableData{ + + private usageType: string = ''; + private displayProgress: boolean = false + private uuid: string = '' // 唯一标识 + private dontAnimateFlag: boolean = false; + private thumbSizeMultiplier: number = 0; + private thumbDelayTime: number = 1000; + private onlyRetrieveFromCache: boolean = false; + private isCacheable: boolean = true; + private gpuEnabled: boolean = false; + private generateCacheKey: string = ""; + private generateResourceKey: string = ""; + private generateDataKey: string = ""; + private signature?: ObjectKey; + private transformations: collections.Array> = new collections.Array>(); + private diskMemoryCachePath: string = ''; + private diskMemoryCache?: DiskLruCache; + private dataFetch: IDataFetch = new DownloadClient(); + + public setDataFetch(value: IDataFetch) { + this.dataFetch = value; + } + + public getDataFetch(): IDataFetch{ + return this.dataFetch; + } + + public setDiskMemoryCachePath(value: string) { + this.diskMemoryCachePath = value; + } + + public getDiskMemoryCachePath(): string{ + return this.diskMemoryCachePath; + } + + + public setDiskMemoryCache(value: DiskLruCache) { + this.diskMemoryCache = value; + } + + public getDiskMemoryCache(): DiskLruCache | undefined{ + return this.diskMemoryCache; + } + + public setTransformations(value: collections.Array>) { + this.transformations = value; + } + + public getTransformations(): collections.Array>{ + return this.transformations; + } + + public setSignature(value: ObjectKey | undefined) { + this.signature = value; + } + + public getSignature(): ObjectKey | undefined{ + return this.signature; + } + + public setGenerateDataKey(value: string) { + this.generateDataKey = value; + } + + public getGenerateDataKey(): string { + return this.generateDataKey; + } + + public setGenerateResourceKey(value: string) { + this.generateResourceKey = value; + } + + public getGenerateResourceKey(): string { + return this.generateResourceKey; + } + + public setGenerateCacheKey(value: string) { + this.generateCacheKey = value; + } + + public getGenerateCacheKey(): string { + return this.generateCacheKey; + } + + public setGpuEnabled(value: boolean) { + this.gpuEnabled = value; + } + + public getGpuEnabled(): boolean { + return this.gpuEnabled; + } + + public setIsCacheable(value: boolean) { + this.isCacheable = value; + } + + public getIsCacheable(): boolean { + return this.isCacheable; + } + + public setOnlyRetrieveFromCache(value: boolean) { + this.onlyRetrieveFromCache = value; + } + + public getOnlyRetrieveFromCache(): boolean { + return this.onlyRetrieveFromCache; + } + + public setThumbDelayTime(value: number) { + this.thumbDelayTime = value; + } + + public getThumbDelayTime(): number { + return this.thumbDelayTime; + } + + public setThumbSizeMultiplier(value: number) { + this.thumbSizeMultiplier = value; + } + + public getThumbSizeMultiplier(): number { + return this.thumbSizeMultiplier; + } + + public setDontAnimateFlag(value: boolean) { + this.dontAnimateFlag = value; + } + + public getDontAnimateFlag(): boolean { + return this.dontAnimateFlag; + } + + public setUuid(value: string) { + this.uuid = value; + } + + public getUuid(): string { + return this.uuid; + } + + public setDisplayProgress(value: boolean) { + this.displayProgress = value; + } + + public getDisplayProgress(): boolean { + return this.displayProgress; + } + + public setUsageType(value: string) { + this.usageType = value; + } + + public getUsageType(): string { + return this.usageType; + } +} \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/TaskParams.ets b/library/src/main/ets/components/imageknife/TaskParams.ets index 4820288..9a37c9a 100644 --- a/library/src/main/ets/components/imageknife/TaskParams.ets +++ b/library/src/main/ets/components/imageknife/TaskParams.ets @@ -15,25 +15,15 @@ import { ObjectKey } from './ObjectKey'; import { Priority, Size } from '../imageknife/RequestOption' import common from '@ohos.app.ability.common' +import { MResource } from './utils/MResource'; export class TaskParams { headers: Map = new Map(); moduleContext?: common.UIAbilityContext = undefined; - transformations: string [][] = [] - usageType: string = '' - displayProgress: boolean = false priority: Priority = Priority.MEDIUM // 优先级 - uuid: string = '' // 唯一标识 - dontAnimateFlag: boolean = false; - thumbSizeMultiplier: number = 0; - thumbDelayTime: number = 1000; size: Size = { width: -1, height: -1 }; - onlyRetrieveFromCache: boolean = false; - isCacheable: boolean = true; - gpuEnabled: boolean = false; - generateCacheKey: string = ""; - generateResourceKey: string = ""; - generateDataKey: string = ""; - signature?: ObjectKey; - diskMemoryCachePath: string = ""; + loadSrc: string | PixelMap | MResource = ""; + placeholderSrc: PixelMap | MResource | undefined = undefined; + errorholderSrc: PixelMap | MResource | undefined = undefined; + retryholderSrc: PixelMap | MResource | undefined = undefined; } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/DataFetchResult.ets b/library/src/main/ets/components/imageknife/networkmanage/DataFetchResult.ets new file mode 100644 index 0000000..76381a2 --- /dev/null +++ b/library/src/main/ets/components/imageknife/networkmanage/DataFetchResult.ets @@ -0,0 +1,19 @@ +/* + * 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 DataFetchResult{ + data?: ArrayBuffer; + error?: string; +} \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets b/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets index 94d2092..ed1c4e6 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets @@ -23,15 +23,17 @@ import loadRequest from '@ohos.request'; import { ImageKnifeGlobal } from '../ImageKnifeGlobal' import common from '@ohos.app.ability.common' import { NetworkDownloadClient } from './NetworkDownloadClient' +import { DataFetchResult } from './DataFetchResult' // 数据加载器 +@Sendable export class DownloadClient implements IDataFetch { - private networkDownloadClient = new NetworkDownloadClient(); - private httpDownloadClient = new HttpDownloadClient(); - private localFileClient = new LoadLocalFileClient(); - private dataShareFileClient = new LoadDataShareFileClient(); + private networkDownloadClient:NetworkDownloadClient = new NetworkDownloadClient(); + private httpDownloadClient:HttpDownloadClient = new HttpDownloadClient(); + private localFileClient:LoadLocalFileClient = new LoadLocalFileClient(); + private dataShareFileClient:LoadDataShareFileClient = new LoadDataShareFileClient(); - loadData(request: RequestOption, onCompleteFunction:(img: ArrayBuffer) => void, onErrorFunction: (err: string) => void) { + async loadData(request: RequestOption): Promise { if (typeof request.loadSrc == 'string') { let fileDir:string = (ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext).filesDir as string; let cacheDir:string = (ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext).cacheDir as string @@ -39,13 +41,17 @@ export class DownloadClient implements IDataFetch { if (request.loadSrc.startsWith(fileDir) || request.loadSrc.startsWith(cacheDir)) { // 本地沙盒 - this.localFileClient.loadData(request, onCompleteFunction, onErrorFunction) + return this.localFileClient.loadData(request) } else if (request.loadSrc.startsWith('datashare://') || request.loadSrc.startsWith('file://')) { - this.dataShareFileClient.loadData(request, onCompleteFunction, onErrorFunction) + return this.dataShareFileClient.loadData(request) } else { // 网络下载 - this.httpDownloadClient.loadData(request, onCompleteFunction, onErrorFunction) + return await this.httpDownloadClient.loadData(request); } + }else{ + let result:DataFetchResult = new DataFetchResult() + result.error ="参数错误!"; + return result; } } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets b/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets index fc07368..1806806 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets @@ -16,69 +16,64 @@ import { IDataFetch } from '../networkmanage/IDataFetch' import { RequestOption } from '../RequestOption' import http from '@ohos.net.http' +import { RequestData } from './RequestData' +import { DataFetchResult } from './DataFetchResult' -// 数据加载器 -class RequestData { - receiveSize: number = 2000 - totalSize: number = 2000 -} +@Sendable export class HttpDownloadClient implements IDataFetch { - async loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) { - try { - let httpRequest = http.createHttp() - let arrayBuffers = new Array(); - httpRequest.on('headersReceive', (header: Object) => { - // 跟服务器连接成功准备下载 - if (request.progressFunc) { - // 进度条为0 - request.progressFunc.asyncSuccess(0) - } - }) - httpRequest.on('dataReceive', (data: ArrayBuffer) => { - // 下载数据流多次返回 - arrayBuffers.push(data); - }) - httpRequest.on('dataReceiveProgress', (data: RequestData) => { - // 下载进度 - if (data != undefined && (typeof data.receiveSize == 'number') && (typeof data.totalSize == 'number')) { - let percent = Math.round(((data.receiveSize * 1.0) / (data.totalSize * 1.0)) * 100) - if (request.progressFunc) { - request.progressFunc.asyncSuccess(percent) - } - } - }) - httpRequest.on('dataEnd', () => { - // 下载完毕 - let combineArray = this.combineArrayBuffers(arrayBuffers); - onComplete(combineArray) - }) - - const headerObj: Record = {} - request.headers.forEach((value, key) => { - headerObj[key] = value - }) - let promise = httpRequest.requestInStream(request.loadSrc as string, { - header: headerObj, - method: http.RequestMethod.GET, - expectDataType: http.HttpDataType.ARRAY_BUFFER, - connectTimeout: 60000, // 可选 默认60000ms - readTimeout: 0, // 可选, 默认为60000ms - usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定 - usingCache: false - }); - await promise.then((data) => { - if (data == 200) { - - } else { - onError(`HttpDownloadClient has error, http code = ` + JSON.stringify(data)) - } - }).catch((err: Error) => { - onError(`HttpDownloadClient has error, http code = ` + JSON.stringify(err)) - }) - } catch (err) { - onError('HttpDownloadClient catch err request uuid =' + request.uuid) - } + async loadData(request: RequestOption) { + let result:DataFetchResult = new DataFetchResult(); + try { + let httpRequest = http.createHttp() + let arrayBuffers = new Array(); + httpRequest.on('headersReceive', (header: Object) => { + // 跟服务器连接成功准备下载 + if (request.progressFunc) { + // 进度条为0 + request.progressFunc.asyncSuccess(0) + } + }) + httpRequest.on('dataReceive', (data: ArrayBuffer) => { + // 下载数据流多次返回 + arrayBuffers.push(data); + }) + httpRequest.on('dataReceiveProgress', (data: RequestData) => { + // 下载进度 + if (data != undefined && (typeof data.receiveSize == 'number') && (typeof data.totalSize == 'number')) { + let percent = Math.round(((data.receiveSize * 1.0) / (data.totalSize * 1.0)) * 100) + if (request.progressFunc) { + request.progressFunc.asyncSuccess(percent) + } + } + }) + httpRequest.on('dataEnd', () => { + // 下载完毕 + }) + const headerObj: Record = {} + request.headers.forEach((value, key) => { + headerObj[key] = value + }) + const data = await httpRequest.requestInStream(request.loadSrc as string, { + header: headerObj, + method: http.RequestMethod.GET, + expectDataType: http.HttpDataType.ARRAY_BUFFER, + connectTimeout: 60000, // 可选 默认60000ms + readTimeout: 0, // 可选, 默认为60000ms + usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定 + usingCache: false + }).catch((err: Error) => { + result.error = `HttpDownloadClient has error, http code = ` + JSON.stringify(err); + }) + if ( data == 200) { + result.data = this.combineArrayBuffers(arrayBuffers); + } else { + result.error = `HttpDownloadClient has error, http code = ` + JSON.stringify(data); + } + } catch (err) { + result.error ='HttpDownloadClient catch err request uuid =' + request.uuid; + } + return result; } combineArrayBuffers(arrayBuffers: ArrayBuffer[]): ArrayBuffer { diff --git a/library/src/main/ets/components/imageknife/networkmanage/IDataFetch.ets b/library/src/main/ets/components/imageknife/networkmanage/IDataFetch.ets index 1fafeb0..4121ceb 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/IDataFetch.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/IDataFetch.ets @@ -14,8 +14,11 @@ */ import { RequestOption } from '../RequestOption' +import lang from '@arkts.lang'; +import { DataFetchResult } from './DataFetchResult'; +type ISendable = lang.ISendable; // 资源加载接口 -export interface IDataFetch { - loadData:(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void)=>void; +export interface IDataFetch extends ISendable{ + loadData(request: RequestOption): DataFetchResult|Promise; } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets b/library/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets index e080a67..acde8af 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets @@ -16,25 +16,29 @@ import { IDataFetch } from '../networkmanage/IDataFetch' import { RequestOption } from '../RequestOption' import fs from '@ohos.file.fs'; import { BusinessError } from '@ohos.base' +import { DataFetchResult } from './DataFetchResult'; +@Sendable export class LoadDataShareFileClient implements IDataFetch { - loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) { + loadData(request: RequestOption) { + let result:DataFetchResult =new DataFetchResult() if (typeof request.loadSrc == 'string') { fs.open(request.loadSrc, fs.OpenMode.READ_ONLY).then((file) => { fs.stat(file.fd).then(stat =>{ let buf = new ArrayBuffer(stat.size); fs.read(file.fd, buf).then((readLen) => { - onComplete(buf); + result.data=buf; fs.close(file.fd); }).catch((err:BusinessError) => { - onError('LoadDataShareFileClient fs.read err happened uri=' + request.loadSrc + " err.msg=" + err?.message + " err.code=" + err?.code) + result.error = 'LoadDataShareFileClient fs.read err happened uri=' + request.loadSrc + " err.msg=" + err?.message + " err.code=" + err?.code; }) }).catch((err:BusinessError) => { - onError('LoadDataShareFileClient fs.stat err happened uri=' + request.loadSrc + " err.msg=" + err?.message + " err.code=" + err?.code) + result.error = 'LoadDataShareFileClient fs.stat err happened uri=' + request.loadSrc + " err.msg=" + err?.message + " err.code=" + err?.code; }) }).catch((err:BusinessError) => { - onError('LoadDataShareFileClient fs.open err happened uri=' + request.loadSrc + " err.msg=" + err?.message + " err.code=" + err?.code) + result.error ='LoadDataShareFileClient fs.open err happened uri=' + request.loadSrc + " err.msg=" + err?.message + " err.code=" + err?.code; }) } + return result; } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets b/library/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets index 89240af..59bdf86 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets @@ -17,19 +17,23 @@ import { IDataFetch } from '../networkmanage/IDataFetch' import { RequestOption } from '../RequestOption' import { FileUtils } from '../../cache/FileUtils' import { BusinessError } from '@ohos.base' +import { DataFetchResult } from './DataFetchResult' + +@Sendable export class LoadLocalFileClient implements IDataFetch { - loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) { + loadData(request: RequestOption) { + let result:DataFetchResult =new DataFetchResult() if (typeof request.loadSrc == 'string') { FileUtils.getInstance().readFilePicAsync(request.loadSrc).then(fileBuffer=>{ if (fileBuffer == null || fileBuffer.byteLength <= 0) { - onError('LoadLocalFileClient loadLocalFileData The File Does Not Exist!Check The File!') + result.error = 'LoadLocalFileClient loadLocalFileData The File Does Not Exist!Check The File!'; } else { - onComplete(fileBuffer); + result.data = fileBuffer } }).catch((err:BusinessError)=>{ - onError('LoadLocalFileClient loadLocalFileData Error Msg ='+err?.message) + result.error ='LoadLocalFileClient loadLocalFileData Error Msg ='+err?.message; }) - } + return result; } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/NetworkDownloadClient.ets b/library/src/main/ets/components/imageknife/networkmanage/NetworkDownloadClient.ets index ae7d9c5..1fcceaf 100644 --- a/library/src/main/ets/components/imageknife/networkmanage/NetworkDownloadClient.ets +++ b/library/src/main/ets/components/imageknife/networkmanage/NetworkDownloadClient.ets @@ -19,12 +19,16 @@ import { SparkMD5 } from '../../3rd_party/sparkmd5/spark-md5' import { FileUtils } from '../../cache/FileUtils' import loadRequest from '@ohos.request'; import { LogUtil } from '../utils/LogUtil' -import { ImageKnifeGlobal } from '../ImageKnifeGlobal' import common from '@ohos.app.ability.common' import { BusinessError } from '@ohos.base' +import { DataFetchResult } from './DataFetchResult' + // 数据加载器 + +@Sendable export class NetworkDownloadClient implements IDataFetch { - loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) { + loadData(request: RequestOption) { + let result:DataFetchResult = new DataFetchResult() let filename:string = SparkMD5.hashBinary(request.generateDataKey); let downloadFolder = request.getFilesPath() + "/" + request.networkCacheFolder; let allpath = request.getFilesPath() + "/" + request.networkCacheFolder + "/" + filename + ".img"; @@ -61,14 +65,14 @@ export class NetworkDownloadClient implements IDataFetch { let downloadPath = allpath; request.downloadFilePath = downloadPath; FileUtils.getInstance().readFilePicAsync(downloadPath).then(arraybuffer=>{ - onComplete(arraybuffer); + result.data=arraybuffer; FileUtils.getInstance().deleteFileAsync(downloadPath).then(()=>{ LogUtil.log('文件名:'+downloadPath+" 文件删除成功!") }).catch((err:BusinessError)=>{ LogUtil.log('文件名:'+downloadPath+" 文件删除失败!") }); }).catch((err:BusinessError)=>{ - onError('NetworkDownloadClient Read File Async Error Msg='+ (err as BusinessError)?.message) + result.error='NetworkDownloadClient Read File Async Error Msg='+ (err as BusinessError)?.message; }) if(loadTask != null) { @@ -86,7 +90,7 @@ export class NetworkDownloadClient implements IDataFetch { loadTask.on('remove', () => {}) loadTask.on('fail', (err) => { - onError('NetworkDownloadClient Download task fail err =' + err) + result.error='NetworkDownloadClient Download task fail err =' + err; if (loadTask!=null) { loadTask.delete().then(result => { if(loadTask != undefined) { @@ -104,11 +108,11 @@ export class NetworkDownloadClient implements IDataFetch { } }) } else { - onError('NetworkDownloadClient downloadTask dismiss!') + result.error='NetworkDownloadClient downloadTask dismiss!' } - }) - .catch((err:BusinessError)=> { - onError("下载子系统download错误捕获,error=" + err.message); + }).catch((err:BusinessError)=> { + result.error="下载子系统download错误捕获,error=" + err.message; }) + return result; } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/networkmanage/RequestData.ets b/library/src/main/ets/components/imageknife/networkmanage/RequestData.ets new file mode 100644 index 0000000..45b2357 --- /dev/null +++ b/library/src/main/ets/components/imageknife/networkmanage/RequestData.ets @@ -0,0 +1,20 @@ +/* + * 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. + */ +// 数据加载器 +@Sendable +export class RequestData { + receiveSize: number = 2000 + totalSize: number = 2000 +} \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/requestmanage/RequestManager.ets b/library/src/main/ets/components/imageknife/requestmanage/RequestManager.ets index 19902fc..a415276 100644 --- a/library/src/main/ets/components/imageknife/requestmanage/RequestManager.ets +++ b/library/src/main/ets/components/imageknife/requestmanage/RequestManager.ets @@ -32,7 +32,7 @@ import { GIFParseImpl } from '../utils/gif/GIFParseImpl' import { GIFFrame } from '../utils/gif/GIFFrame' import { LogUtil } from '../../imageknife/utils/LogUtil' import { BusinessError } from '@ohos.base' -import taskpool from '@ohos.taskpool'; +import { DataFetchResult } from '../networkmanage/DataFetchResult' export enum Stage { @@ -66,10 +66,12 @@ export class RequestManager { private mIDataFetch: IDataFetch; private mIResourceFetch: IResourceFetch; private mParseImageUtil: IParseImage; + private diskMemoryCache: DiskLruCache; - constructor(option: RequestOption, dataFetch: IDataFetch, resourceFetch: IResourceFetch) { + constructor(option: RequestOption,diskMemoryCache: DiskLruCache, dataFetch: IDataFetch, resourceFetch: IResourceFetch) { this.options = option; + this.diskMemoryCache = diskMemoryCache; // 网络下载能力 this.mIDataFetch = dataFetch; @@ -135,16 +137,19 @@ export class RequestManager { } // 加载网络资源 - private loadSourceFromNetwork(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike, onError: (reason?: BusinessError | string) => void) { + private async loadSourceFromNetwork(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike, onError: (reason?: BusinessError | string) => void) { try { LogUtil.log("ImageKnife RequestManager loadSourceFromNetwork") - let success = (arraybuffer: ArrayBuffer) => { - this.downloadSuccess(request, arraybuffer, onComplete, onError) + let result: DataFetchResult = await this.mIDataFetch.loadData(request); + if(result.error){ + onError(result.error) + }else{ + if(result.data){ + this.downloadSuccess(request, result.data, onComplete, onError) + }else{ + onError("datafetch data is null") + } } - let error = (errorMsg: string) => { - onError(errorMsg) - } - this.mIDataFetch.loadData(request, success, error); } catch (e) { LogUtil.error("ImageKnife RequestManager loadSourceFromNetwork error") } @@ -199,7 +204,7 @@ export class RequestManager { // 加载磁盘缓存 原图 private loadDiskFromSource(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike, onError: (reason?: BusinessError | string) => void) { LogUtil.log("ImageKnife RequestManager loadDiskFromSource") - let cached = DiskLruCache.getFileCacheByFile(request.diskMemoryCachePath, request.generateDataKey); + let cached = this.diskMemoryCache.get(request.generateDataKey); if (cached != null && cached.byteLength > 0) { LogUtil.log("ImageKnife loadDiskFromSource load resource from DiskLruCache") this.parseDiskFile2PixelMap(request, cached, onComplete, onError) @@ -213,7 +218,7 @@ export class RequestManager { // 加载磁盘缓存 变换后图片 private loadDiskFromTransform(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike, onError: (reason?: BusinessError | string) => void) { LogUtil.log("ImageKnife RequestManager loadDiskFromTransform") - let cached = DiskLruCache.getFileCacheByFile(request.diskMemoryCachePath, request.generateResourceKey); + let cached = this.diskMemoryCache.get(request.generateResourceKey); if (cached != null) { LogUtil.log("ImageKnife loadDiskFromTransform load resource from DiskLruCache") this.parseDiskTransformFile2PixelMap(request, cached, onComplete, onError) @@ -396,7 +401,7 @@ export class RequestManager { // 保存二级磁盘缓存 Promise.resolve(source) .then((arraybuffer: ArrayBuffer) => { - DiskLruCache.saveFileCacheOnlyFile(this.options.diskMemoryCachePath, this.options.generateDataKey,arraybuffer); + this.diskMemoryCache.set(this.options.generateDataKey,arraybuffer); }) .catch((err: BusinessError) => { LogUtil.log('download file is =' + ImageKnifeData.GIF + 'and save diskLruCache error =' + (err as BusinessError)) @@ -408,7 +413,7 @@ export class RequestManager { // 保存二级磁盘缓存 Promise.resolve(source) .then((arraybuffer: ArrayBuffer) => { - DiskLruCache.saveFileCacheOnlyFile(this.options.diskMemoryCachePath, this.options.generateDataKey,arraybuffer); + this.diskMemoryCache.set(this.options.generateDataKey,arraybuffer); }) .catch((err: BusinessError) => { LogUtil.log('download file is =' + ImageKnifeData.SVG + 'and save diskLruCache error =' + (err as BusinessError)) @@ -474,7 +479,7 @@ export class RequestManager { private async saveCacheAndDisk(value: PixelMap, filetype: string, onComplete: (value: PixelMap) => void | PromiseLike, source: ArrayBuffer) { let save2DiskCache = (arraybuffer: ArrayBuffer) => { - DiskLruCache.saveFileCacheOnlyFile(this.options.diskMemoryCachePath, this.options.generateDataKey,arraybuffer); + this.diskMemoryCache.set(this.options.generateDataKey,arraybuffer); // 落盘之后需要主动移除当前request并且调用下一个加载 let removeCurrentAndSearchNextRun = this.options.removeCurrentAndSearchNext; removeCurrentAndSearchNextRun(); diff --git a/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets b/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets index 2f8510f..0c43a36 100644 --- a/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets +++ b/library/src/main/ets/components/imageknife/resourcemanage/ParseResClientBase64.ets @@ -29,7 +29,7 @@ export class ParseResClientBase64 implements IResourceFetch { if (resType == ResourceTypeEts.MEDIA) { let moduleContext = ContextCacheProxy.getInstance() .contextGetValue(res.moduleName, context); - (moduleContext.resourceManager as resourceManager.ResourceManager) + (moduleContext?.resourceManager as resourceManager.ResourceManager) .getMediaContentBase64(resId) .then(data => { let matchReg = ';base64,'; diff --git a/library/src/main/ets/components/imageknife/transform/TransformUtils.ets b/library/src/main/ets/components/imageknife/transform/TransformUtils.ets index 8f5ea50..43f6283 100644 --- a/library/src/main/ets/components/imageknife/transform/TransformUtils.ets +++ b/library/src/main/ets/components/imageknife/transform/TransformUtils.ets @@ -40,6 +40,7 @@ import { CenterCrop } from './pixelmap/CenterCrop' import { CenterInside } from './pixelmap/CenterInside' import { FitCenter } from './pixelmap/FitCenter' import { CropTransformation, CropType } from './CropTransformation' +import { collections } from '@kit.ArkTS' export class TransformUtils { static centerCrop(buf: ArrayBuffer, outWidth: number, outHeihgt: number, @@ -179,11 +180,11 @@ export class TransformUtils { }) } - static addTransformations (data: string [][]) { + static addTransformations (data: collections.Array>) { let transformations: Array> = new Array(); - for (let i = 0; i < data.length; i++) { - let className = data[i][0] as string; - let params = data[i][1] as string; + data.forEach((value:collections.Array ) => { + let className = value.shift(); + let params = value.shift() as string; switch (className) { case "BlurTransformation": let paramList: number [] = JSON.parse(params); @@ -271,7 +272,7 @@ export class TransformUtils { default: break } - } + }); return transformations; } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/utils/MResource.ets b/library/src/main/ets/components/imageknife/utils/MResource.ets new file mode 100644 index 0000000..0826d53 --- /dev/null +++ b/library/src/main/ets/components/imageknife/utils/MResource.ets @@ -0,0 +1,22 @@ +/* + * 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 MResource { + bundleName?: string; + moduleName?: string; + id?: number; + params?: []; + type?: number; +} diff --git a/sharedlibrary/src/main/ets/Index.ets b/sharedlibrary/src/main/ets/Index.ets index a506039..8597fed 100644 --- a/sharedlibrary/src/main/ets/Index.ets +++ b/sharedlibrary/src/main/ets/Index.ets @@ -31,6 +31,7 @@ export { NONE } from '@ohos/imageknife' export { RESOURCE } from '@ohos/imageknife' export { EngineKeyInterface } from '@ohos/imageknife' export { EngineKeyFactories } from '@ohos/imageknife' +export { DataFetchResult } from '@ohos/imageknife' /** * compress