[Issues: #I9DWXC]修复自定义DataFetch接口不生效问题

Signed-off-by: baofeng <baofeng6@h-partners.com>
This commit is contained in:
baofeng 2024-04-19 10:44:38 +08:00
parent a2a8700eb4
commit f84b793eca
29 changed files with 681 additions and 228 deletions

View File

@ -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
- 修复设置磁盘容量最大值出现闪退

View File

@ -460,6 +460,10 @@ HSP场景适配:
非HSP场景不影响原功能, ImageKnifeOption配置类新增的可选参数context可以不传, RquestOption配置类新增的接口可以不调用。
注意:
基于性能优化的原因2.1.2-rc.13及以后版本引用了API12 Sendable接口至此以后的版本只支持API12。
## 目录结构
```

View File

@ -4,8 +4,8 @@
{
"name": "default",
"signingConfig": "default",
"compileSdkVersion": 10,
"compatibleSdkVersion": 10
"compileSdkVersion": 12,
"compatibleSdkVersion": 12
}
],
"buildModeSet": [

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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 })
}

View File

@ -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",

View File

@ -50,6 +50,7 @@
"pages/testReusePhotoPage",
"pages/testImageKnifeCache",
"pages/webpImageTestPage",
"pages/testStopPlayingGifPage"
"pages/testStopPlayingGifPage",
"pages/testImageKnifeDataFetch"
]
}

View File

@ -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

View File

@ -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<string, DiskCacheEntry> = new collections.Map<string, DiskCacheEntry>()
// 获取键对应的值
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<string, DiskCacheEntry>) => void) {
this.map.forEach(fn)
}
// 清除键值对
clear() {
this.map.clear()
}
// 遍历key
keys(): IterableIterator<string>{
return this.map.keys()
}
}

View File

@ -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 = ''

View File

@ -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<string, DiskCacheEntry> = new CustomMap<string, DiskCacheEntry>()
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;

View File

@ -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<ImageKnifeData>, 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<collections.Array<string>> = new collections.Array<collections.Array<string>>();
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<string>;
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<PixelMap | GIFFrame[]> {
async function taskExecute(sendData:SendableData,taskData:TaskParams): Promise<PixelMap | GIFFrame[]> {
//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<PixelMap | GIFFrame[]>(manager.process);
}
}

View File

@ -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;

View File

@ -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<collections.Array<string>> = new collections.Array<collections.Array<string>>();
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<collections.Array<string>>) {
this.transformations = value;
}
public getTransformations(): collections.Array<collections.Array<string>>{
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;
}
}

View File

@ -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<string, Object> = new Map<string, Object>();
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;
}

View File

@ -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;
}

View File

@ -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<DataFetchResult> {
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;
}
}
}

View File

@ -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<ArrayBuffer>();
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<string, Object> = {}
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<ArrayBuffer>();
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<string, Object> = {}
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 {

View File

@ -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<DataFetchResult>;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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<ArrayBuffer>;
private mParseImageUtil: IParseImage<PixelMap>;
private diskMemoryCache: DiskLruCache;
constructor(option: RequestOption, dataFetch: IDataFetch, resourceFetch: IResourceFetch<ArrayBuffer>) {
constructor(option: RequestOption,diskMemoryCache: DiskLruCache, dataFetch: IDataFetch, resourceFetch: IResourceFetch<ArrayBuffer>) {
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<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
private async loadSourceFromNetwork(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, 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<ImageKnifeData>, 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<ImageKnifeData>, 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<ImageKnifeData>, 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();

View File

@ -29,7 +29,7 @@ export class ParseResClientBase64 implements IResourceFetch<ArrayBuffer> {
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,';

View File

@ -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<collections.Array<string>>) {
let transformations: Array<BaseTransform<PixelMap>> = 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<string> ) => {
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;
}
}

View File

@ -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;
}

View File

@ -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