[Issues: #I9DWXC]修复自定义DataFetch接口不生效问题
Signed-off-by: baofeng <baofeng6@h-partners.com>
This commit is contained in:
parent
a2a8700eb4
commit
f84b793eca
|
@ -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
|
||||
- 修复设置磁盘容量最大值出现闪退
|
||||
|
|
|
@ -460,6 +460,10 @@ HSP场景适配:
|
|||
|
||||
非HSP场景不影响原功能, ImageKnifeOption配置类新增的可选参数context可以不传, RquestOption配置类新增的接口可以不调用。
|
||||
|
||||
注意:
|
||||
|
||||
基于性能优化的原因,2.1.2-rc.13及以后版本引用了API12 Sendable接口,至此以后的版本只支持API12。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compileSdkVersion": 10,
|
||||
"compatibleSdkVersion": 10
|
||||
"compileSdkVersion": 12,
|
||||
"compatibleSdkVersion": 12
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 })
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
"pages/testReusePhotoPage",
|
||||
"pages/testImageKnifeCache",
|
||||
"pages/webpImageTestPage",
|
||||
"pages/testStopPlayingGifPage"
|
||||
"pages/testStopPlayingGifPage",
|
||||
"pages/testImageKnifeDataFetch"
|
||||
]
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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 = ''
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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>;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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,';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue