ImageKnife3.x分支合并到master分支
Signed-off-by: wangyingjun01 <wangyingjun5@h-partners.com>
This commit is contained in:
parent
7d39ff5129
commit
45b1fbc591
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent, } from '@ohos/libraryimageknife'
|
||||
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestDurationAndPlayTimesPage {
|
||||
build() {
|
||||
Column() {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: "https://n.sinaimg.cn/default/944aebbe/20230131/diamond_1.gif",
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
}).width(300)
|
||||
.height(300)
|
||||
.backgroundColor(Color.Orange)
|
||||
Image("https://n.sinaimg.cn/default/944aebbe/20230131/diamond_1.gif")
|
||||
.width(300)
|
||||
.height(300)
|
||||
.backgroundColor(Color.Orange)
|
||||
.objectFit(ImageFit.Contain)
|
||||
.margin({top:20})
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
|
@ -1,366 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
FitCenter,
|
||||
ImageKnifeComponent,
|
||||
ImageKnifeData,
|
||||
ImageKnifeGlobal,
|
||||
ImageKnifeOption,
|
||||
RequestOption
|
||||
} from '@ohos/libraryimageknife'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import { fitter, sampleNone } from '@ohos/imageknife';
|
||||
|
||||
let pngUrl = $r('app.media.pngSample');
|
||||
let jpgUrl = $r('app.media.jpgSample');
|
||||
let svgUrl = $r('app.media.svgSample');
|
||||
let gifUrl = $r('app.media.gifSample');
|
||||
let bmpUrl = $r('app.media.bmpSample');
|
||||
let webpUrl = $r('app.media.webpSample');
|
||||
let imageKnife = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State originalMSquarePixelMap?: PixelMap = undefined;
|
||||
@State mSquarePixelMap?: PixelMap = undefined;
|
||||
@State h: number = 0
|
||||
@State w: number = 0
|
||||
@State originalBytesNumber: number = 0
|
||||
@State bytesNumber: number = 0
|
||||
@State url: string = ''
|
||||
@State network: Boolean = false
|
||||
@State imageKnifeOption: ImageKnifeOption = {
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
|
||||
transformSquare1(mUrl: string|Resource|PixelMap) {
|
||||
let imageKnifeOption: RequestOption = new RequestOption();
|
||||
imageKnifeOption.load(mUrl)
|
||||
.addListener({
|
||||
callback: (err: BusinessError | string, data: ImageKnifeData) => {
|
||||
this.originalMSquarePixelMap = data.drawPixelMap?.imagePixelMap as PixelMap;
|
||||
this.originalBytesNumber = (data.drawPixelMap?.imagePixelMap as PixelMap).getPixelBytesNumber()
|
||||
return false;
|
||||
}
|
||||
})
|
||||
imageKnife?.call(imageKnifeOption);
|
||||
}
|
||||
|
||||
transformSquare2(mUrl: string|Resource|PixelMap) {
|
||||
let imageKnifeOption: RequestOption = new RequestOption();
|
||||
let a = new fitter()
|
||||
imageKnifeOption.load(mUrl)
|
||||
.addListener({
|
||||
callback: (err: BusinessError | string, data: ImageKnifeData) => {
|
||||
this.mSquarePixelMap = data.drawPixelMap?.imagePixelMap as PixelMap;
|
||||
this.bytesNumber = (data.drawPixelMap?.imagePixelMap as PixelMap).getPixelBytesNumber()
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.setImageViewSize({ width: this.w, height: this.h })
|
||||
.downsampleOf(a)
|
||||
imageKnife?.call(imageKnifeOption);
|
||||
}
|
||||
|
||||
@Builder
|
||||
TextInputSample() {
|
||||
Flex() {
|
||||
TextInput({ placeholder: '输入宽' })
|
||||
.onChange((enterKeyType) => {
|
||||
this.w = Number(enterKeyType)
|
||||
})
|
||||
TextInput({ placeholder: '输入高' })
|
||||
.onChange((enterKeyType) => {
|
||||
this.h = Number(enterKeyType)
|
||||
})
|
||||
}.padding(20)
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Row() {
|
||||
Button('切换网络图片')
|
||||
.onClick(() => {
|
||||
this.network = !this.network
|
||||
})
|
||||
Text('输入网络图片url')
|
||||
TextInput({ placeholder: '输入url' })
|
||||
.onChange((urls) => {
|
||||
this.url = urls
|
||||
})
|
||||
}
|
||||
|
||||
if (this.network) {
|
||||
Column() {
|
||||
Text('原图')
|
||||
Flex() {
|
||||
Button('png')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(this.url);
|
||||
|
||||
});
|
||||
Button('svg')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(this.url);
|
||||
|
||||
});
|
||||
Button('bmp')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(this.url);
|
||||
|
||||
});
|
||||
Button('jpg')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(this.url);
|
||||
|
||||
});
|
||||
// Button('gif')
|
||||
// .onClick(() => {
|
||||
// this.transformSquare1(this.url);
|
||||
//
|
||||
// });
|
||||
// Button('webp')
|
||||
// .onClick(() => {
|
||||
// this.transformSquare1(this.url);
|
||||
//
|
||||
// });
|
||||
}.margin({ top: 20, bottom: 20 })
|
||||
|
||||
Text("原图字节大小:" + this.originalBytesNumber)
|
||||
Column() {
|
||||
if (this.originalMSquarePixelMap) {
|
||||
Image(this.originalMSquarePixelMap == undefined ? '' : this.originalMSquarePixelMap!)
|
||||
.objectFit(ImageFit.Fill)
|
||||
.width(200)
|
||||
.height(200)
|
||||
.margin({ top: 10 })
|
||||
}
|
||||
Text('component用法')
|
||||
|
||||
}.height(300).width('100%').backgroundColor(Color.Pink)
|
||||
|
||||
Text('降采样图片')
|
||||
Flex() {
|
||||
Button('png')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(this.url);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: pngUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
downsampling: new fitter()
|
||||
}
|
||||
});
|
||||
Button('svg')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(this.url);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: svgUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
downsampling: new fitter()
|
||||
}
|
||||
|
||||
});
|
||||
Button('bmp')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(this.url);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: bmpUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
downsampling: new fitter()
|
||||
}
|
||||
});
|
||||
Button('jpg')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(this.url);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: jpgUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
downsampling: new fitter()
|
||||
}
|
||||
});
|
||||
// Button('gif')
|
||||
// .onClick(() => {
|
||||
// // this.transformSquare2(this.url);
|
||||
// this.imageKnifeOption = {
|
||||
// loadSrc: gifUrl,
|
||||
// placeholderSrc: $r('app.media.icon_loading'),
|
||||
// errorholderSrc: $r('app.media.icon_failed'),
|
||||
// downsampling: new fitter()
|
||||
// }
|
||||
// });
|
||||
// Button('webp')
|
||||
// .onClick(() => {
|
||||
// // this.transformSquare2(this.url);
|
||||
// this.imageKnifeOption = {
|
||||
// loadSrc: webpUrl,
|
||||
// placeholderSrc: $r('app.media.icon_loading'),
|
||||
// errorholderSrc: $r('app.media.icon_failed'),
|
||||
// downsampling: new fitter()
|
||||
// }
|
||||
// });
|
||||
}.margin({ top: 20, bottom: 20 })
|
||||
|
||||
Text("降采样字节大小:" + this.bytesNumber)
|
||||
this.TextInputSample()
|
||||
Column() {
|
||||
if (this.mSquarePixelMap) {
|
||||
Image(this.mSquarePixelMap == undefined ? '' : this.mSquarePixelMap!)
|
||||
.objectFit(ImageFit.Fill)
|
||||
.width(200)
|
||||
.height(200)
|
||||
.margin({ top: 10 })
|
||||
}
|
||||
Text('component用法')
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }).width(200).height(200)
|
||||
}.height(300).width('100%').backgroundColor(Color.Pink)
|
||||
}.backgroundColor(Color.Orange)
|
||||
} else {
|
||||
Column() {
|
||||
Text('原图')
|
||||
Flex() {
|
||||
Button('png')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(pngUrl);
|
||||
|
||||
});
|
||||
Button('svg')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(svgUrl);
|
||||
|
||||
});
|
||||
Button('bmp')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(bmpUrl);
|
||||
|
||||
});
|
||||
Button('jpg')
|
||||
.onClick(() => {
|
||||
this.transformSquare1(jpgUrl);
|
||||
|
||||
});
|
||||
// Button('gif')
|
||||
// .onClick(() => {
|
||||
// this.transformSquare1(gifUrl);
|
||||
//
|
||||
// });
|
||||
// Button('webp')
|
||||
// .onClick(() => {
|
||||
// this.transformSquare1(webpUrl);
|
||||
//
|
||||
// });
|
||||
}.margin({ top: 20, bottom: 20 })
|
||||
|
||||
Text("原图字节大小:" + this.originalBytesNumber)
|
||||
Column() {
|
||||
if (this.originalMSquarePixelMap) {
|
||||
Image(this.originalMSquarePixelMap == undefined ? '' : this.originalMSquarePixelMap!)
|
||||
.objectFit(ImageFit.Fill)
|
||||
.width(200)
|
||||
.height(200)
|
||||
.margin({ top: 10 })
|
||||
}
|
||||
Text('component用法')
|
||||
|
||||
}.height(300).width('100%').backgroundColor(Color.Pink)
|
||||
|
||||
Text('降采样图片')
|
||||
Flex() {
|
||||
Button('png')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(pngUrl);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: pngUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
});
|
||||
Button('svg')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(svgUrl);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: svgUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
|
||||
});
|
||||
Button('bmp')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(bmpUrl);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: bmpUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
});
|
||||
Button('jpg')
|
||||
.onClick(() => {
|
||||
this.transformSquare2(jpgUrl);
|
||||
this.imageKnifeOption = {
|
||||
loadSrc: jpgUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
});
|
||||
// Button('gif')
|
||||
// .onClick(() => {
|
||||
// // this.transformSquare2(gifUrl);
|
||||
// this.imageKnifeOption = {
|
||||
// loadSrc: gifUrl,
|
||||
// placeholderSrc: $r('app.media.icon_loading'),
|
||||
// errorholderSrc: $r('app.media.icon_failed'),
|
||||
// }
|
||||
// });
|
||||
// Button('webp')
|
||||
// .onClick(() => {
|
||||
// // this.transformSquare2(webpUrl);
|
||||
// this.imageKnifeOption = {
|
||||
// loadSrc: webpUrl,
|
||||
// placeholderSrc: $r('app.media.icon_loading'),
|
||||
// errorholderSrc: $r('app.media.icon_failed'),
|
||||
// }
|
||||
// });
|
||||
}.margin({ top: 20, bottom: 20 })
|
||||
|
||||
Text("降采样字节大小:" + this.bytesNumber)
|
||||
this.TextInputSample()
|
||||
Column() {
|
||||
if (this.mSquarePixelMap) {
|
||||
Image(this.mSquarePixelMap == undefined ? '' : this.mSquarePixelMap!)
|
||||
.objectFit(ImageFit.Fill)
|
||||
.width(200)
|
||||
.height(200)
|
||||
.margin({ top: 10 })
|
||||
}
|
||||
Text('component用法')
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }).width(200).height(200)
|
||||
}.height("100%").width('100%').backgroundColor(Color.Pink)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
CustomDataFetchClient,
|
||||
DataFetchResult,
|
||||
DownloadClient,
|
||||
ImageKnifeComponent,
|
||||
ImageKnifeGlobal,
|
||||
ImageKnifeOption,
|
||||
LogUtil,
|
||||
ScaleType
|
||||
} from '@ohos/libraryimageknife';
|
||||
|
||||
import http from '@ohos.net.http';
|
||||
|
||||
class CommonDataSource <T> implements IDataSource {
|
||||
private dataArray: T[] = []
|
||||
private listeners: DataChangeListener[] = []
|
||||
|
||||
constructor(element: []) {
|
||||
this.dataArray = element
|
||||
}
|
||||
|
||||
public getData(index: number) {
|
||||
return this.dataArray[index]
|
||||
}
|
||||
|
||||
public totalCount(): number {
|
||||
return this.dataArray.length
|
||||
}
|
||||
|
||||
public addData(index: number, data: T[]): void {
|
||||
this.dataArray = this.dataArray.concat(data)
|
||||
this.notifyDataAdd(index)
|
||||
}
|
||||
|
||||
unregisterDataChangeListener(listener: DataChangeListener): void {
|
||||
const pos = this.listeners.indexOf(listener);
|
||||
if (pos >= 0) {
|
||||
this.listeners.splice(pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
registerDataChangeListener(listener: DataChangeListener): void {
|
||||
if (this.listeners.indexOf(listener) < 0) {
|
||||
this.listeners.push(listener)
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataAdd(index: number): void {
|
||||
this.listeners.forEach((listener: DataChangeListener) => {
|
||||
listener.onDataAdd(index)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestCustomDataFetchClientWithPage {
|
||||
@State hotCommendList: CommonDataSource<string> = new CommonDataSource<string>([])
|
||||
@State singleImageKnifeOption: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
@State isSingleImageVisible: boolean = true;
|
||||
@State isAllImageVisible: boolean = false;
|
||||
@State isCustom: boolean = false;
|
||||
private isAllImageAdded: boolean = false;
|
||||
private isCancelImageAdded: boolean = false;
|
||||
private data: Array<string> = [
|
||||
"http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg"
|
||||
]
|
||||
private addData: Array<string> = [
|
||||
"http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg"
|
||||
|
||||
]
|
||||
private cancelData: Array<string> = [
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg"
|
||||
]
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.hotCommendList.addData(this.hotCommendList.totalCount(), this.data)
|
||||
LogUtil.log('TestCustomDataFetch about to appear.')
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
|
||||
Button("单个图片").margin(16).onClick(() => {
|
||||
LogUtil.log('TestCustomDataFetch click single.');
|
||||
this.isSingleImageVisible = true;
|
||||
this.isAllImageVisible = false;
|
||||
|
||||
this.singleImageKnifeOption = {
|
||||
loadSrc: 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg',
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
customGetImage: custom
|
||||
}
|
||||
})
|
||||
Button("全部图片").margin(16).onClick(() => {
|
||||
LogUtil.log('TestCustomDataFetch click all.');
|
||||
this.isSingleImageVisible = false;
|
||||
this.isAllImageVisible = true;
|
||||
|
||||
ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new CustomDataFetchClient());
|
||||
if (!this.isAllImageAdded) {
|
||||
this.hotCommendList.addData(this.hotCommendList.totalCount(), this.addData);
|
||||
this.isAllImageAdded = true;
|
||||
}
|
||||
})
|
||||
|
||||
Button("取消自定义全部图片").margin(16).onClick(() => {
|
||||
LogUtil.log('TestCustomDataFetch click cancel.');
|
||||
this.isSingleImageVisible = false;
|
||||
this.isAllImageVisible = true;
|
||||
|
||||
ImageKnifeGlobal.getInstance().getImageKnife()?.replaceDataFetch(new DownloadClient());
|
||||
if (!this.isCancelImageAdded) {
|
||||
this.hotCommendList.addData(this.hotCommendList.totalCount(), this.cancelData);
|
||||
this.isCancelImageAdded = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 单个图片使用自定义网络栈
|
||||
ImageKnifeComponent({ imageKnifeOption: this.singleImageKnifeOption })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.margin({ top: 50 })
|
||||
.visibility(this.isSingleImageVisible ? Visibility.Visible : Visibility.None)
|
||||
|
||||
// 全部图片使用自定义网络栈
|
||||
Column() {
|
||||
Grid() {
|
||||
LazyForEach(this.hotCommendList, (item: string) => {
|
||||
GridItem() {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: item,
|
||||
placeholderSrc: $r('app.media.icon'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
placeholderScaleType: ScaleType.CENTER_CROP,
|
||||
mainScaleType: ScaleType.CENTER_CROP,
|
||||
}
|
||||
}).width('100%').height('100%')
|
||||
}.width('40%').height(200)
|
||||
}, (item: string) => JSON.stringify(item))
|
||||
}
|
||||
.columnsTemplate('1fr 1fr')
|
||||
.columnsGap(8)
|
||||
.rowsGap(10)
|
||||
.width('100%')
|
||||
.hitTestBehavior(HitTestMode.None)
|
||||
.maxCount(10)
|
||||
}.margin({ top: 5 })
|
||||
.visibility(this.isAllImageVisible ? Visibility.Visible : Visibility.None)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
|
||||
@Concurrent
|
||||
async function custom(context: Context, loadSrc: string): Promise<DataFetchResult> {
|
||||
let result: DataFetchResult = new DataFetchResult();
|
||||
try {
|
||||
let arrayBuffers = new Array<ArrayBuffer>();
|
||||
let httpRequest = http.createHttp()
|
||||
httpRequest.on('headersReceive', (header: Object) => {
|
||||
// 跟服务器连接成功准备下载
|
||||
})
|
||||
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
|
||||
// 下载数据流多次返回
|
||||
arrayBuffers.push(data);
|
||||
})
|
||||
httpRequest.on('dataEnd', () => {
|
||||
// 下载完毕
|
||||
})
|
||||
|
||||
const resultCode = await httpRequest.requestInStream(loadSrc as string,
|
||||
{
|
||||
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 = 'TestCustomDataFetchClientWithPage requestInStream error.' + JSON.stringify(err);
|
||||
})
|
||||
if (resultCode == 200) {
|
||||
//let combineArray = this.combineArrayBuffers(arrayBuffers);
|
||||
// 计算多个ArrayBuffer的总字节大小
|
||||
let totalByteLength = 0;
|
||||
for (const arrayBuffer of arrayBuffers) {
|
||||
totalByteLength += arrayBuffer.byteLength;
|
||||
}
|
||||
// 创建一个新的ArrayBuffer
|
||||
const combinedArrayBuffer = new ArrayBuffer(totalByteLength);
|
||||
|
||||
// 创建一个Uint8Array来操作新的ArrayBuffer
|
||||
const combinedUint8Array = new Uint8Array(combinedArrayBuffer);
|
||||
|
||||
// 依次复制每个ArrayBuffer的内容到新的ArrayBuffer中
|
||||
let offset = 0;
|
||||
for (const arrayBuffer of arrayBuffers) {
|
||||
const sourceUint8Array = new Uint8Array(arrayBuffer);
|
||||
combinedUint8Array.set(sourceUint8Array, offset);
|
||||
offset += sourceUint8Array.length;
|
||||
}
|
||||
result.data = combinedArrayBuffer;
|
||||
} else {
|
||||
result.error = 'TestCustomDataFetchClientWithPage error. resultCode = ' + resultCode;
|
||||
}
|
||||
console.log('TestCustomDataFetch single onComplete, code = ' + resultCode + ',length = ' + result.data?.byteLength);
|
||||
} catch (error) {
|
||||
result.error = 'TestCustomDataFetchClientWithPage error' + error.stack;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestGifPlayTimesPage {
|
||||
@State ImageKnifeOption1: ImageKnifeOption = {
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Text("测试gif播放次数").fontSize(25)
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Button("加载网络gif").onClick(() => {
|
||||
this.ImageKnifeOption1 = {
|
||||
loadSrc: "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
Button("设置gif播放1次").onClick(() => {
|
||||
this.ImageKnifeOption1 = {
|
||||
loadSrc: "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
gif: {
|
||||
playTimes: 1
|
||||
}
|
||||
}
|
||||
})
|
||||
Button("设置gif播放2次").onClick(() => {
|
||||
this.ImageKnifeOption1 = {
|
||||
loadSrc: "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
gif: {
|
||||
playTimes: 2
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption1 }).width(300).height(300).borderWidth(3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,239 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 {
|
||||
ImageKnifeComponent,
|
||||
ImageKnifeOption,
|
||||
ImageKnifeGlobal,
|
||||
ImageKnife,
|
||||
ImageKnifeData,
|
||||
RequestOption,
|
||||
Size,
|
||||
CacheType
|
||||
} from '@ohos/libraryimageknife'
|
||||
import image from '@ohos.multimedia.image';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
|
||||
let imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeCache {
|
||||
@State url: string = '';
|
||||
@State urlGif: string = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658';
|
||||
@State urlPng: string = 'https://img-blog.csdnimg.cn/20191215043500229.png';
|
||||
@State urlJpg: string = 'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB';
|
||||
@State urlBmp: string = 'https://img-blog.csdn.net/20140514114029140';
|
||||
@State urlWebp: string = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
||||
@State imagePixelMap: PixelMap | undefined = undefined;
|
||||
@State imagePixelMap_: PixelMap | undefined = undefined;
|
||||
private index_: number = -1;
|
||||
private tempSize: number = 200;
|
||||
private timeId = -1;
|
||||
private comSize: Size = {
|
||||
width: this.tempSize,
|
||||
height: this.tempSize,
|
||||
}
|
||||
@State imageKnifeOption: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
};
|
||||
loadSuccess = (data: ImageKnifeData) => {
|
||||
clearTimeout(this.timeId);
|
||||
if (data.isPixelMap()) {
|
||||
if (data.drawPixelMap) {
|
||||
let pixelmap = data.drawPixelMap.imagePixelMap
|
||||
if (pixelmap) {
|
||||
if (this.index_ == 1) {
|
||||
this.imagePixelMap = pixelmap;
|
||||
} else if (this.index_ == 2) {
|
||||
this.imagePixelMap_ = pixelmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.isGIFFrame()) {
|
||||
let index: number = 0
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let renderGif = () => {
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let pixelmap = data.drawGIFFrame.imageGIFFrames[index].drawPixelMap
|
||||
let delay = data.drawGIFFrame.imageGIFFrames[index].delay
|
||||
if (pixelmap) {
|
||||
if (this.index_ == 1) {
|
||||
this.imagePixelMap = pixelmap;
|
||||
} else if (this.index_ == 2) {
|
||||
this.imagePixelMap_ = pixelmap;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
if (index == data.drawGIFFrame.imageGIFFrames.length - 1) {
|
||||
index = 0
|
||||
}
|
||||
this.timeId = setTimeout(renderGif, data!.drawGIFFrame!.imageGIFFrames![index].delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
renderGif()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loadError = (err: BusinessError) => {
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
|
||||
Text('图片内存和磁盘读取').fontSize(30);
|
||||
Text('加载的缓存时候关闭掉网络').fontSize(15);
|
||||
|
||||
Row() {
|
||||
Button('png')
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlPng;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('bmp')
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlBmp;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('webp')
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlWebp;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('jpg')
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlJpg;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('gif')
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlGif;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Row() {
|
||||
Button('缓存图片')
|
||||
.onClick(() => {
|
||||
this.index_ = 1;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Cache, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
|
||||
Button('磁盘图片')
|
||||
.onClick(() => {
|
||||
this.index_ = 2;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Disk, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
|
||||
Button('默认')
|
||||
.onClick(() => {
|
||||
this.index_ = 2;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Default, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
}
|
||||
|
||||
Text('网络图').fontSize(15);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
Text('缓存图').fontSize(15);
|
||||
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.imagePixelMap as image.PixelMap
|
||||
}
|
||||
})
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
Text('磁盘图').fontSize(15);
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.imagePixelMap_ as image.PixelMap
|
||||
}
|
||||
})
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
}
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width('100%')
|
||||
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
|
||||
}
|
||||
|
||||
aboutToDisappear() {
|
||||
|
||||
}
|
||||
|
||||
onBackPress() {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeHeic {
|
||||
@State imageKnifeOption1: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.yunHeic'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
|
||||
@State flag: boolean = true;
|
||||
|
||||
build() {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
|
||||
Button("heic图片测试")
|
||||
.onClick(() => {
|
||||
this.flag = !this.flag
|
||||
}).margin({ top: 15 })
|
||||
if(this.flag) {
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
||||
}
|
||||
}.width('100%').height(400).backgroundColor(Color.Pink)
|
||||
}
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 {
|
||||
HeaderOptions,ImageKnife,ImageKnifeComponent,ImageKnifeData,ImageKnifeGlobal,RequestOption,ImageKnifeOption,ObjectKey
|
||||
} from '@ohos/libraryimageknife'
|
||||
import image from '@ohos.multimedia.image'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
|
||||
const TAG = "TEST-"
|
||||
let timeId = -1
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeHttpRequestHeader1 {
|
||||
@State pixelMap: PixelMap | undefined = undefined;
|
||||
@State pixelMap1: PixelMap | undefined = undefined;
|
||||
@State domeType1: boolean = false;
|
||||
@State domeType2: boolean = false;
|
||||
@State successHeader: string = "requestOption调用成功";
|
||||
@State errorHeader: string = "requestOption调用失败";
|
||||
@State allKeySame: string = "全局添加header和request成功的键相同值不同";
|
||||
@State allKeyNoSame: string = "全局添加header和request成功的键不同";
|
||||
@State clearnAllHeader: string = "清空全局header";
|
||||
|
||||
@State message: string = "图片header属性测试";
|
||||
|
||||
imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife()
|
||||
// RequestOption调用
|
||||
load(src: string | image.PixelMap | Resource, type: string, num: number) {
|
||||
clearTimeout(timeId)
|
||||
let request = new RequestOption()
|
||||
if (type == 'error') {
|
||||
request.addHeader('xx', src)
|
||||
} else {
|
||||
request.addHeader('refer', src)
|
||||
}
|
||||
//清理缓存
|
||||
request.signature = new ObjectKey(new Date().getTime().toString())
|
||||
request.load(src)
|
||||
.addListener({ callback: (err: BusinessError | string, data: ImageKnifeData) => {
|
||||
if (data.isPixelMap()) {
|
||||
if (data.drawPixelMap) {
|
||||
let pixelmap = data.drawPixelMap.imagePixelMap
|
||||
if (pixelmap) {
|
||||
if (num == 1) {
|
||||
this.pixelMap = pixelmap
|
||||
} else if (num == 2) {
|
||||
this.pixelMap1 = pixelmap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.isGIFFrame()) {
|
||||
let index: number = 0
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let renderGif = () => {
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let pixelmap = data.drawGIFFrame.imageGIFFrames[index].drawPixelMap
|
||||
let delay = data.drawGIFFrame.imageGIFFrames[index].delay
|
||||
if (pixelmap) {
|
||||
if (num == 1) {
|
||||
this.pixelMap = pixelmap
|
||||
} else if (num == 2) {
|
||||
this.pixelMap1 = pixelmap
|
||||
}
|
||||
}
|
||||
index++;
|
||||
if (index == data.drawGIFFrame.imageGIFFrames.length - 1) {
|
||||
index = 0
|
||||
}
|
||||
timeId = setTimeout(renderGif, data!.drawGIFFrame!.imageGIFFrames![index].delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
renderGif()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
console.log(TAG + "error:" + JSON.stringify(err));
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
let imageknife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife()
|
||||
if (imageknife != undefined) {
|
||||
imageknife.call(request)
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
setHeader() {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.pixelMap as image.PixelMap
|
||||
}
|
||||
}).width(200).height(200).borderWidth(1)
|
||||
}
|
||||
@Builder
|
||||
setHeader1() {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.pixelMap1 as image.PixelMap
|
||||
}
|
||||
}).width(200).height(200).borderWidth(1)
|
||||
}
|
||||
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Text(`${this.message}`)
|
||||
.width("300vp")
|
||||
.height("60vp")
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontSize("30fp")
|
||||
.fontWeight(FontWeight.Bold)
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
|
||||
Button(this.successHeader)
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
this.domeType1 = !this.domeType1
|
||||
this.load('http://1.94.37.200:7070/AntiTheftChain/downloadImage', 'success', 1)
|
||||
})
|
||||
if (this.domeType1) {
|
||||
this.setHeader()
|
||||
}
|
||||
Button(this.errorHeader)
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
this.domeType2 = !this.domeType2
|
||||
this.load('http://1.94.37.200:7070/AntiTheftChain/downloadImage', 'error', 2)
|
||||
})
|
||||
if (this.domeType2) {
|
||||
this.setHeader1()
|
||||
}
|
||||
Button(this.allKeySame)
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
this.imageKnife?.addHeader('refer','test')
|
||||
})
|
||||
Button(this.allKeyNoSame)
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
this.imageKnife?.addHeader('ceshi','http://1.94.37.200:7070/AntiTheftChain/downloadImage')
|
||||
})
|
||||
Button(this.clearnAllHeader)
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
this.imageKnife?.deleteHeader('refer');
|
||||
this.imageKnife?.deleteHeader('ceshi');
|
||||
})
|
||||
}
|
||||
}.width("100%")
|
||||
.justifyContent(FlexAlign.Start)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeCache {
|
||||
@State imageKnifeOption: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Text('测试失败场景时关闭掉网络').fontSize(15);
|
||||
Row() {
|
||||
Button('测试加载成功/失败监听')
|
||||
.onClick(() => {
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
onLoadListener: {
|
||||
onLoadSuccess: (data) => {
|
||||
console.log('Load Successful: ' + data);
|
||||
return data;
|
||||
},
|
||||
onLoadFailed: (err) => {
|
||||
console.error('Load Failed Reason: ' + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Text('网络图').fontSize(15);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
}
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
|
||||
}
|
||||
|
||||
aboutToDisappear() {
|
||||
|
||||
}
|
||||
|
||||
onBackPress() {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeNetPlaceholder {
|
||||
@State imageKnifeOption: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
@State imageKnifeOption1: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
@State imageKnifeOption2: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Text('string类型占位图支持内存和磁盘读取').fontSize(30);
|
||||
Text('验证磁盘有无图片可以先主图缓存一张图片,再退出应用').fontSize(15);
|
||||
Text('仅第一次打开应用加载主图可以看到效果,因主图第二次加载速度很快').fontSize(15);
|
||||
|
||||
Row() {
|
||||
Button('缓存一张图片作为占位图 图一')
|
||||
.onClick(() => {
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Text('当图一没有展示,会从磁盘中拿占位图').fontSize(15);
|
||||
Text('当图一展示时,会从内存中拿占位图,不会走磁盘逻辑').fontSize(15);
|
||||
|
||||
Text('下图展示的为后备回调符的图片').fontSize(15);
|
||||
ImageKnifeComponent({ imageKnifeOption: {loadSrc:$r('app.media.mask_starfish')} })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
Text('下图展示的主图为图二string类型的占位图').fontSize(15);
|
||||
Text('图一:').fontSize(20);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
Row() {
|
||||
Button('展示已缓存的占位图')
|
||||
.onClick(() => {
|
||||
this.imageKnifeOption1 =
|
||||
{
|
||||
loadSrc : $r('app.media.pngSample'),
|
||||
placeholderSrc: 'https://img-blog.csdn.net/20140514114029140',
|
||||
fallbackSrc: $r('app.media.mask_starfish'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
})
|
||||
|
||||
Button('当占位图未缓存时展示后备回调符')
|
||||
.onClick(() => {
|
||||
this.imageKnifeOption2 =
|
||||
{
|
||||
loadSrc : $r('app.media.gifSample'),
|
||||
placeholderSrc: 'https://img0.baidu.com/it/u=2794536113,2700219306&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
|
||||
fallbackSrc: $r('app.media.mask_starfish'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Text('展示已缓存的占位图,如图一未加载过则会显示后备回调符').fontSize(15);
|
||||
Text('图二:').fontSize(20);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
Text('占位图未缓存展示后备回调符,如图三').fontSize(15);
|
||||
Text('图三:').fontSize(20);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
}
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width('100%')
|
||||
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
|
||||
}
|
||||
|
||||
aboutToDisappear() {
|
||||
|
||||
}
|
||||
|
||||
onBackPress() {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,269 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
ImageKnifeComponent,
|
||||
ImageKnifeOption,
|
||||
ImageKnifeGlobal,
|
||||
ImageKnife,
|
||||
ImageKnifeData,
|
||||
Size,
|
||||
CacheType
|
||||
} from '@ohos/libraryimageknife'
|
||||
import image from '@ohos.multimedia.image';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
|
||||
let imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct testImageKnifeRemoveCache {
|
||||
@State url: string = '';
|
||||
@State urlGif: string = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658';
|
||||
@State urlPng: string = 'https://img-blog.csdnimg.cn/20191215043500229.png';
|
||||
@State urlJpg: string = 'https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB';
|
||||
@State urlBmp: string = 'https://img-blog.csdn.net/20140514114029140';
|
||||
@State urlWebp: string = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
||||
@State imagePixelMap: PixelMap | undefined = undefined;
|
||||
@State imagePixelMap_: PixelMap | undefined = undefined;
|
||||
private index_: number = -1;
|
||||
private tempSize: number = 200;
|
||||
private timeId = -1;
|
||||
private comSize: Size = {
|
||||
width: this.tempSize,
|
||||
height: this.tempSize,
|
||||
}
|
||||
@State imageKnifeOption: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
};
|
||||
loadSuccess = (data: ImageKnifeData) => {
|
||||
clearTimeout(this.timeId);
|
||||
if (data.isPixelMap()) {
|
||||
if (data.drawPixelMap) {
|
||||
let pixelmap = data.drawPixelMap.imagePixelMap;
|
||||
if (pixelmap) {
|
||||
if (this.index_ == 1) {
|
||||
this.imagePixelMap = pixelmap;
|
||||
} else if (this.index_ == 2) {
|
||||
this.imagePixelMap_ = pixelmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.isGIFFrame()) {
|
||||
let index: number = 0
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let renderGif = () => {
|
||||
if (data.drawGIFFrame) {
|
||||
if (data.drawGIFFrame.imageGIFFrames) {
|
||||
let pixelmap = data.drawGIFFrame.imageGIFFrames[index].drawPixelMap;
|
||||
let delay = data.drawGIFFrame.imageGIFFrames[index].delay;
|
||||
if (pixelmap) {
|
||||
if (this.index_ == 1) {
|
||||
this.imagePixelMap = pixelmap;
|
||||
} else if (this.index_ == 2) {
|
||||
this.imagePixelMap_ = pixelmap;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
if (index == data.drawGIFFrame.imageGIFFrames.length - 1) {
|
||||
index = 0;
|
||||
}
|
||||
this.timeId = setTimeout(renderGif, data!.drawGIFFrame!.imageGIFFrames![index].delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
renderGif();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loadError = (err: BusinessError) => {
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
|
||||
Text('图片内存和磁盘缓存删除').fontSize(30);
|
||||
Text('测试删除缓存时候关闭掉网络').fontSize(15);
|
||||
|
||||
Row() {
|
||||
Button('png')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlPng;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('bmp')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlBmp;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('webp')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlWebp;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('jpg')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlJpg;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
|
||||
Button('gif')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 0;
|
||||
this.url = this.urlGif;
|
||||
this.imageKnifeOption =
|
||||
{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Row() {
|
||||
Button('缓存图片')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 1;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Cache, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
|
||||
Button('磁盘图片')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
this.index_ = 2;
|
||||
imageKnife?.isUrlExist(this.url, CacheType.Disk, this.comSize).then(this.loadSuccess)
|
||||
.catch(this.loadError);
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Row() {
|
||||
Button('清除全部缓存')
|
||||
.onClick(() => {
|
||||
imageKnife?.removeAllMemoryCache();
|
||||
imageKnife?.removeAllFileCache();
|
||||
})
|
||||
|
||||
Button('清除全部内存缓存')
|
||||
.onClick(() => {
|
||||
imageKnife?.removeAllMemoryCache();
|
||||
})
|
||||
|
||||
Button('清除全部磁盘缓存')
|
||||
.onClick(() => {
|
||||
imageKnife?.removeAllFileCache();
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Row() {
|
||||
Button('清除指定内存缓存')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
imageKnife?.removeMemoryCache(this.url);
|
||||
})
|
||||
|
||||
Button('清除指定磁盘缓存')
|
||||
.margin({right:10})
|
||||
.onClick(() => {
|
||||
imageKnife?.removeFileCache(this.url);
|
||||
})
|
||||
}.margin({top: 20})
|
||||
|
||||
Text('网络图').fontSize(15);
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption })
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
Text('缓存图').fontSize(15);
|
||||
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.imagePixelMap as image.PixelMap
|
||||
}
|
||||
})
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
Text('磁盘图').fontSize(15);
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.imagePixelMap_ as image.PixelMap
|
||||
}
|
||||
})
|
||||
.width(200)
|
||||
.height(200)
|
||||
.backgroundColor(Color.Orange)
|
||||
|
||||
}
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width('100%')
|
||||
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
|
||||
}
|
||||
|
||||
aboutToDisappear() {
|
||||
|
||||
}
|
||||
|
||||
onBackPress() {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent } from '@ohos/libraryimageknife'
|
||||
|
||||
class BasicDataSource implements IDataSource {
|
||||
private listeners: DataChangeListener[] = [];
|
||||
private originDataArray: StringData[] = [];
|
||||
|
||||
public totalCount(): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public getData(index: number): StringData {
|
||||
return this.originDataArray[index];
|
||||
}
|
||||
|
||||
registerDataChangeListener(listener: DataChangeListener): void {
|
||||
if (this.listeners.indexOf(listener) < 0) {
|
||||
console.info('add listener');
|
||||
this.listeners.push(listener);
|
||||
}
|
||||
}
|
||||
|
||||
unregisterDataChangeListener(listener: DataChangeListener): void {
|
||||
const pos = this.listeners.indexOf(listener);
|
||||
if (pos >= 0) {
|
||||
console.info('remove listener');
|
||||
this.listeners.splice(pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataReload(): void {
|
||||
this.listeners.forEach(listener => {
|
||||
listener.onDataReloaded();
|
||||
})
|
||||
}
|
||||
|
||||
notifyDataAdd(index: number): void {
|
||||
this.listeners.forEach(listener => {
|
||||
listener.onDataAdd(index);
|
||||
})
|
||||
}
|
||||
|
||||
notifyDataChange(index: number): void {
|
||||
this.listeners.forEach(listener => {
|
||||
listener.onDataChange(index);
|
||||
})
|
||||
}
|
||||
|
||||
notifyDataDelete(index: number): void {
|
||||
this.listeners.forEach(listener => {
|
||||
listener.onDataDelete(index);
|
||||
})
|
||||
}
|
||||
|
||||
notifyDataMove(from: number, to: number): void {
|
||||
this.listeners.forEach(listener => {
|
||||
listener.onDataMove(from, to);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class MyDataSource extends BasicDataSource {
|
||||
private dataArray: StringData[] = [];
|
||||
|
||||
public totalCount(): number {
|
||||
return this.dataArray.length;
|
||||
}
|
||||
|
||||
public getData(index: number): StringData {
|
||||
return this.dataArray[index];
|
||||
}
|
||||
|
||||
public addData(index: number, data: StringData): void {
|
||||
this.dataArray.splice(index, 0, data);
|
||||
this.notifyDataAdd(index);
|
||||
}
|
||||
|
||||
public pushData(data: StringData): void {
|
||||
this.dataArray.push(data);
|
||||
this.notifyDataAdd(this.dataArray.length - 1);
|
||||
}
|
||||
|
||||
public reloadData(): void {
|
||||
this.notifyDataReload();
|
||||
}
|
||||
}
|
||||
|
||||
class StringData {
|
||||
message: string;
|
||||
imgSrc: string;
|
||||
|
||||
constructor(message: string, imgSrc: string) {
|
||||
this.message = message;
|
||||
this.imgSrc = imgSrc;
|
||||
}
|
||||
}
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestReuseAbleComponent {
|
||||
@State dataArray: Array<string> = [
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg",
|
||||
"http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg",
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg",
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg",
|
||||
"http://f.hiphotos.baidu.com/image/pic/item/4034970a304e251f503521f5a586c9177e3e53f9.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg",
|
||||
"http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg",
|
||||
"http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg",
|
||||
"http://d.hiphotos.baidu.com/image/pic/item/b58f8c5494eef01f119945cbe2fe9925bc317d2a.jpg",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/e824b899a9014c08878b2c4c0e7b02087af4f4a3.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/6d81800a19d8bc3e770bd00d868ba61ea9d345f2.jpg",
|
||||
"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
|
||||
'https://img-blog.csdnimg.cn/20191215043500229.png',
|
||||
'https://img-blog.csdn.net/20140514114029140',
|
||||
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp'
|
||||
]
|
||||
private data: MyDataSource = new MyDataSource();
|
||||
private index: number = 0
|
||||
private timeId: number = -1
|
||||
|
||||
aboutToAppear() {
|
||||
for (let i = 0; i <= 4; i++) {
|
||||
this.data.pushData(new StringData(`Hello ${i}`, this.dataArray[i]));
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
List({ space: 3 }) {
|
||||
LazyForEach(this.data, (item: StringData, index: number) => {
|
||||
ListItem() {
|
||||
Column() {
|
||||
Text(item.message).fontSize(50)
|
||||
.onAppear(() => {
|
||||
console.info("appear:" + item.message)
|
||||
})
|
||||
ReusableComponent({ url: item.imgSrc })
|
||||
.width(500)
|
||||
.height(200)
|
||||
}.margin({ left: 10, right: 10 })
|
||||
}
|
||||
.onClick(() => {
|
||||
item.message += '00';
|
||||
this.data.reloadData();
|
||||
})
|
||||
}, (item: StringData, index: number) => JSON.stringify(item))
|
||||
}.cachedCount(5)
|
||||
.onReachEnd(()=>{
|
||||
clearTimeout(this.timeId)
|
||||
this.timeId = setTimeout(()=>{
|
||||
this.data.reloadData()
|
||||
if(this.data.totalCount() <= this.dataArray.length) {
|
||||
this.index = this.data.totalCount()
|
||||
for (let index = this.index; index <= this.index + 4; index++) {
|
||||
this.data.addData(index,new StringData(`Hello ${index}`, this.dataArray[index]));
|
||||
}
|
||||
}
|
||||
},1500)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Reusable
|
||||
@Component
|
||||
struct ReusableComponent {
|
||||
@State url: string = ""
|
||||
|
||||
aboutToReuse(params: Record<string, string>) {
|
||||
this.url = params.url
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading')
|
||||
}
|
||||
})
|
||||
}.width("100%").height("100%")
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent } from '@ohos/libraryimageknife'
|
||||
import { ImageKnifeOption } from '@ohos/libraryimageknife'
|
||||
import display from '@ohos.display';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestStopPlayingGifPage {
|
||||
@State message: string = 'gif暂停播放测试'
|
||||
@State eventType: string = '';
|
||||
@State options: ImageKnifeOption = {
|
||||
loadSrc: $r('app.media.app_icon'),
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Column() {
|
||||
Text(`${this.message}`)
|
||||
.width("300vp")
|
||||
.height("60vp")
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontSize("30fp")
|
||||
.fontWeight(FontWeight.Bold)
|
||||
Button("加载gif图")
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
console.log("加载多帧gif")
|
||||
this.options = {
|
||||
loadSrc: $r('app.media.gifSample'),
|
||||
placeholderSrc:$r('app.media.icon_loading'),
|
||||
}
|
||||
})
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Text("控制")
|
||||
Button("开启")
|
||||
.onClick(() => {
|
||||
this.options.autoPlay = true;
|
||||
}).margin({ left: 3 })
|
||||
|
||||
Button("暂停")
|
||||
.onClick(() => {
|
||||
this.options.autoPlay = false;
|
||||
}).margin({ left: 3 })
|
||||
}.width('100%')
|
||||
.height(40).backgroundColor(Color.Pink).margin({bottom:5})
|
||||
ImageKnifeComponent({ imageKnifeOption: this.options })
|
||||
.margin(16)
|
||||
.width(300)
|
||||
.height(300)
|
||||
}
|
||||
.width("100%")
|
||||
.height("100%")
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}
|
||||
.width("100%")
|
||||
.height("100%")
|
||||
}
|
||||
aboutToAppear() {
|
||||
console.log('CTT:TestManyNetImageLoadWithPage display Height: '+ display.getDefaultDisplaySync().height)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent } from '@ohos/libraryimageknife';
|
||||
|
||||
class CommonDataSource <T> implements IDataSource {
|
||||
private dataArray: T[] = []
|
||||
private listeners: DataChangeListener[] = []
|
||||
|
||||
constructor(element: []) {
|
||||
this.dataArray = element
|
||||
}
|
||||
|
||||
public getData(index: number) {
|
||||
return this.dataArray[index]
|
||||
}
|
||||
|
||||
public totalCount(): number {
|
||||
return this.dataArray.length
|
||||
}
|
||||
|
||||
public addData(index: number, data: T[]): void {
|
||||
this.dataArray = this.dataArray.concat(data)
|
||||
this.notifyDataAdd(index)
|
||||
}
|
||||
|
||||
unregisterDataChangeListener(listener: DataChangeListener): void {
|
||||
const pos = this.listeners.indexOf(listener);
|
||||
if (pos >= 0) {
|
||||
this.listeners.splice(pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
registerDataChangeListener(listener: DataChangeListener): void {
|
||||
if (this.listeners.indexOf(listener) < 0) {
|
||||
this.listeners.push(listener)
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataAdd(index: number): void {
|
||||
this.listeners.forEach((listener: DataChangeListener) => {
|
||||
listener.onDataAdd(index)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestVisiblePage {
|
||||
@State currentScene: string = 'LazyForEach';
|
||||
@State hotCommendList: CommonDataSource<string> = new CommonDataSource<string>([]);
|
||||
@State data: Array<string> = [
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg",
|
||||
"http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg",
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg",
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg",
|
||||
"http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg",
|
||||
"http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg",
|
||||
"http://d.hiphotos.baidu.com/image/pic/item/b58f8c5494eef01f119945cbe2fe9925bc317d2a.jpg",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/e824b899a9014c08878b2c4c0e7b02087af4f4a3.jpg",
|
||||
"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
|
||||
'https://img-blog.csdnimg.cn/20191215043500229.png',
|
||||
'https://img-blog.csdn.net/20140514114029140',
|
||||
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/R9aT7lpEEVxawo4.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/1V6c63lKLGPlKVo.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/2NxCo49xAB1L96K.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/P6gH3pWBGw7L6dD.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/MKosgAWo5VKpo9Z.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/pA2S9lvNpMY4X3N.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/69MiA9VxKdkzjWR.png!thumb-w321-webp75",
|
||||
"https://material-center-pre.meitudata.com/material/image/6228901fd8ddd6350.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/P98i3gdgDw3Rmx5.png!thumb-w321-webp75",
|
||||
"https://stage.meitudata.com/public/creator/ed70a3c696c8e7b.jpg!thumb-w321-webp75",
|
||||
"https://material-center-pre.meitudata.com/material/image/6194a57b5b9ef7678.jpg!thumb-w321-webp75",
|
||||
"https://material-center-pre.meitudata.com/material/image/6189f29b48f165954.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/0lZCW9BrDgMroLL.jpeg!thumb-w321-webp75",
|
||||
"https://xximg1.meitudata.com/V2jTkoYa96.jpeg!thumb-w321-webp75",
|
||||
"http://xximg2.meitudata.com/Z9DCJpkB2l.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/zwdte8R2e5KMMmm.jpeg!thumb-w321-webp75",
|
||||
"https://xximg1.meitudata.com/mlahyxNxjN.jpeg!thumb-w321-webp75",
|
||||
"https://xximg1.meitudata.com/8OkUwBympV.jpeg!thumb-w321-webp75",
|
||||
"https://xximg1.meitudata.com/9nzUydyWeB.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/R9aT7lpEEVxawo4.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/Ymju0r3deAl7xoJ.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/8zPcB0y4vdreG1d.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/1V6c63lKLGPlKVo.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/Z9dtor442OY76KV.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/2NxCo49xAB1L96K.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/xxtool-pre/material/P6gH3pWBGw7L6dD.jpeg!thumb-w321-webp75",
|
||||
"https://material-center-pre.meitudata.com/material/image/6228901fd8ddd6350.jpeg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/deRP83dkdlR4.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/rPJ1vKjJY6jz.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/z8K3P249ZmVW.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/e4xlVkl0BzMy.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/B6MleZrWeMvj.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/B6MleZ1ae5Ry.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/EyvzkoPgakDL.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/3zVRo1E16vZG.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/3zVRo1EdvZ0W.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/1mLMv1kd2BLZ.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/8NXRMzE019aB.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/0XDRo7xdPkVx.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/V06dg1RJ8pDr.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/2p5Ro1VDZvxR.png!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/1mLMWyxNVMAe.jpg!thumb-w321-webp75",
|
||||
"https://xxtool-release.zone1.meitudata.com/7d8RoA7DXYB9.jpg!thumb-w321-webp75",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg",
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg",
|
||||
"http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg",
|
||||
"http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg",
|
||||
"http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg",
|
||||
"http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg",
|
||||
"http://d.hiphotos.baidu.com/image/pic/item/b58f8c5494eef01f119945cbe2fe9925bc317d2a.jpg",
|
||||
"http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg",
|
||||
"http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg",
|
||||
"http://b.hiphotos.baidu.com/image/pic/item/e824b899a9014c08878b2c4c0e7b02087af4f4a3.jpg",
|
||||
]
|
||||
private listScroller: Scroller = new Scroller();
|
||||
|
||||
|
||||
aboutToAppear() {
|
||||
this.hotCommendList.addData(this.hotCommendList.totalCount(), this.data)
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Flex(){
|
||||
Button('懒加载场景').flexGrow(1).height(40).onClick(() => {
|
||||
this.currentScene = 'LazyForEach';
|
||||
this.listScroller.scrollToIndex(0);
|
||||
})
|
||||
Button('懒加载+复用场景').flexGrow(1).height(40).onClick(() => {
|
||||
this.currentScene = 'ReuseAndLazyForEach';
|
||||
this.listScroller.scrollToIndex(0);
|
||||
})
|
||||
Button('其他场景').flexGrow(1).height(40).onClick(() => {
|
||||
this.currentScene = 'ForEach';
|
||||
this.listScroller.scrollToIndex(0);
|
||||
})
|
||||
}.padding({top: 10, bottom: 10})
|
||||
List({ space: 20, scroller: this.listScroller }) {
|
||||
if(this.currentScene == 'LazyForEach') {
|
||||
this.renderLazyForEachComponent();
|
||||
} else if (this.currentScene == 'ReuseAndLazyForEach') {
|
||||
this.renderReuseComponent();
|
||||
} else {
|
||||
this.renderForEachComponent();
|
||||
}
|
||||
}
|
||||
|
||||
.width("100%")
|
||||
.height("100%")
|
||||
.backgroundColor(0xFAEEE0)
|
||||
}.width("100%").height("100%")
|
||||
}
|
||||
|
||||
@Builder
|
||||
renderLazyForEachComponent () {
|
||||
LazyForEach(this.hotCommendList, (item: string, index: number) => {
|
||||
ListItem() {
|
||||
MyComponent({ url: item, index: index + '' }).width("100%").height("100%")
|
||||
}.width(200).height(200).backgroundColor(Color.Orange)
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
renderReuseComponent () {
|
||||
LazyForEach(this.hotCommendList, (item: string, index: number) => {
|
||||
ListItem() {
|
||||
ReuseComponent({ url: item, index: index + '' }).width("100%").height("100%")
|
||||
}.width(200).height(200).backgroundColor(Color.Orange)
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
renderForEachComponent () {
|
||||
ForEach(this.data, (item: string, index: number) => {
|
||||
ListItem() {
|
||||
MyComponent({ url: item, index: index + '' }).width("100%").height("100%")
|
||||
}.width(200).height(200).backgroundColor(Color.Orange)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 没有复用的组件
|
||||
@Component
|
||||
struct MyComponent {
|
||||
@Prop url: string = "";
|
||||
@Prop index: string = '0';
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Flex({ direction: FlexDirection.Column}) {
|
||||
Text(this.index).fontSize(18).fontColor(Color.White)
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption:{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
}).height(150)
|
||||
}
|
||||
}.width("100%").height("100%")
|
||||
}
|
||||
}
|
||||
|
||||
// 复用组件
|
||||
@Reusable
|
||||
@Component
|
||||
struct ReuseComponent {
|
||||
@Prop url: string = "";
|
||||
@Prop index: string = '0';
|
||||
|
||||
aboutToReuse(params: Record<string, string>) {
|
||||
this.url = params.url;
|
||||
this.index = params.index;
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Flex({ direction: FlexDirection.Column}) {
|
||||
Text(this.index).fontSize(18).fontColor(Color.White)
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption:{
|
||||
loadSrc: this.url,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
}
|
||||
}).height(150)
|
||||
}
|
||||
}.width("100%").height("100%")
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* 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 { ImageKnifeComponent } from '@ohos/libraryimageknife'
|
||||
import { ImageKnifeOption,ScaleType } from '@ohos/libraryimageknife'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct webpImageTestPage {
|
||||
@State message: string = 'webp图片'
|
||||
@State options: ImageKnifeOption = {
|
||||
loadSrc: $r('app.media.app_icon')
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Column() {
|
||||
Text(`${this.message}`)
|
||||
.width("300vp")
|
||||
.height("60vp")
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontSize("50fp")
|
||||
.fontWeight(FontWeight.Bold)
|
||||
Button("加载单帧webp")
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
console.log("加载单帧webp")
|
||||
this.options = {
|
||||
loadSrc: $r('app.media.webpSample'),
|
||||
placeholderSrc:$r('app.media.icon_loading'),
|
||||
mainScaleType:ScaleType.FIT_XY
|
||||
}
|
||||
})
|
||||
Button("加载多帧webp")
|
||||
.margin(16)
|
||||
.onClick(() => {
|
||||
console.log("加载多帧webp")
|
||||
this.options = {
|
||||
loadSrc: $r('app.media.webpAtanta'),
|
||||
placeholderSrc:$r('app.media.icon_loading'),
|
||||
mainScaleType:ScaleType.FIT_XY
|
||||
}
|
||||
})
|
||||
ImageKnifeComponent({ imageKnifeOption: this.options })
|
||||
.margin(16)
|
||||
.width(200)
|
||||
.height(100)
|
||||
.clip(true)
|
||||
.borderRadius(50)
|
||||
}
|
||||
.width("100%")
|
||||
.height("100%")
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}
|
||||
.width("100%")
|
||||
.height("100%")
|
||||
}
|
||||
}
|
|
@ -5,9 +5,8 @@
|
|||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"phone",
|
||||
"tablet",
|
||||
"2in1"
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
|
|
|
@ -1,64 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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,
|
||||
* 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
|
||||
import { ImageKnifeOption } from '@ohos/imageknife'
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
|
||||
import { ImageKnifeOption,ImageKnifeData } from "@ohos/imageknife"
|
||||
|
||||
export default function ImageKnifeOptionTest() {
|
||||
describe('ImageKnifeOptionTest', ()=> {
|
||||
describe('ImageKnifeOptionTest',() => {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
beforeAll( ()=> {
|
||||
beforeAll(() => {
|
||||
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
beforeEach( ()=> {
|
||||
});
|
||||
beforeEach(() => {
|
||||
// Presets an action, which is performed before each unit test case starts.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
afterEach( ()=> {
|
||||
});
|
||||
afterEach(() => {
|
||||
// Presets a clear action, which is performed after each unit test case ends.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
afterAll( ()=> {
|
||||
});
|
||||
afterAll(() => {
|
||||
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
|
||||
it('onLoadListener',0, ()=> {
|
||||
});
|
||||
it('onLoadListener', 0, () => {
|
||||
let a = 'abc';
|
||||
let b: string = '';
|
||||
let imageKnifeOption: ImageKnifeOption = {
|
||||
loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
||||
onLoadListener: {
|
||||
onLoadSuccess: (data) => {
|
||||
if (typeof data == 'string') {
|
||||
b = data;
|
||||
let imageData:ImageKnifeData = {
|
||||
source: "",
|
||||
imageWidth: 0,
|
||||
imageHeight: 0,
|
||||
}
|
||||
let ImageKnifeOption: ImageKnifeOption = {
|
||||
loadSrc: $r("app.media.rabbit"),
|
||||
onLoadListener: {
|
||||
onLoadFailed: (err) => {
|
||||
console.error("Load Failed Reason: " + err);
|
||||
},
|
||||
onLoadSuccess: (data,imageknifeData) => {
|
||||
if(typeof data == 'string') {
|
||||
return b = data;
|
||||
}
|
||||
imageData = imageknifeData
|
||||
return data;
|
||||
},
|
||||
onLoadFailed: (err) => {
|
||||
console.log('Load Failed Reason: '+err);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
if(imageKnifeOption.onLoadListener && imageKnifeOption.onLoadListener.onLoadSuccess && imageKnifeOption.onLoadListener.onLoadFailed) {
|
||||
imageKnifeOption.onLoadListener.onLoadSuccess(a);
|
||||
imageKnifeOption.onLoadListener.onLoadFailed(a);
|
||||
if (ImageKnifeOption.onLoadListener && ImageKnifeOption.onLoadListener.onLoadSuccess && ImageKnifeOption.onLoadListener.onLoadFailed) {
|
||||
ImageKnifeOption.onLoadListener.onLoadSuccess(a,imageData);
|
||||
ImageKnifeOption.onLoadListener.onLoadFailed(a);
|
||||
}
|
||||
expect(a).assertEqual(b);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
|
@ -5,9 +5,8 @@
|
|||
"description": "$string:module_test_desc",
|
||||
"mainElement": "TestAbility",
|
||||
"deviceTypes": [
|
||||
"phone",
|
||||
"tablet",
|
||||
"2in1"
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
{
|
||||
"modelVersion": "5.0.0",
|
||||
"hvigorVersion": "4.3.0",
|
||||
"dependencies": {
|
||||
},
|
||||
"execution": {
|
||||
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */
|
||||
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
|
||||
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
|
||||
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
|
||||
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"logging": {
|
||||
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
|
||||
},
|
||||
"debugging": {
|
||||
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"nodeOptions": {
|
||||
// "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */
|
||||
"@ohos/hvigor-ohos-plugin": "4.3.0"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Hvigor startup script, version 1.0.0
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# NODE_HOME - location of a Node home dir
|
||||
# or
|
||||
# Add /usr/local/nodejs/bin to the PATH environment variable
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
HVIGOR_APP_HOME=$(dirname $(readlink -f $0))
|
||||
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
|
||||
warn() {
|
||||
echo ""
|
||||
echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo ""
|
||||
echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
|
||||
}
|
||||
|
||||
fail() {
|
||||
error "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Determine node to start hvigor wrapper script
|
||||
if [ -n "${NODE_HOME}" ];then
|
||||
EXECUTABLE_NODE="${NODE_HOME}/bin/node"
|
||||
if [ ! -x "$EXECUTABLE_NODE" ];then
|
||||
fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
|
||||
fi
|
||||
else
|
||||
EXECUTABLE_NODE="node"
|
||||
which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
|
||||
fi
|
||||
|
||||
# Check hvigor wrapper script
|
||||
if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
|
||||
fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
|
||||
fi
|
||||
|
||||
# start hvigor-wrapper script
|
||||
exec "${EXECUTABLE_NODE}" \
|
||||
"${HVIGOR_WRAPPER_SCRIPT}" "$@"
|
|
@ -0,0 +1,57 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Hvigor startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
|
||||
set NODE_EXE=node.exe
|
||||
|
||||
goto start
|
||||
|
||||
:start
|
||||
@rem Find node.exe
|
||||
if defined NODE_HOME goto findNodeFromNodeHome
|
||||
|
||||
%NODE_EXE% --version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the NODE_HOME variable in your environment to match the
|
||||
echo location of your NodeJs installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findNodeFromNodeHome
|
||||
set NODE_HOME=%NODE_HOME:"=%
|
||||
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
|
||||
|
||||
if exist "%NODE_EXE_PATH%" goto execute
|
||||
echo.
|
||||
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the NODE_HOME variable in your environment to match the
|
||||
echo location of your NodeJs installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Execute hvigor
|
||||
"%NODE_EXE%" %WRAPPER_MODULE_PATH% %*
|
||||
|
||||
:fail
|
||||
exit /b 1
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* 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 { AsyncLock } from '../imageknife/utils/base/AsyncLock';
|
||||
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)
|
||||
}
|
||||
|
||||
// 添加键值对
|
||||
async put(key: string, value: DiskCacheEntry): Promise<DiskCacheEntry | undefined>{
|
||||
if (key == null || value == null) {
|
||||
throw new Error('key or value is invalid,checking the parameter');
|
||||
}
|
||||
const lock = new AsyncLock();
|
||||
await lock.acquire()
|
||||
try {
|
||||
let pre = this.map.get(key) as DiskCacheEntry | undefined;
|
||||
if (this.hasKey(key)) {
|
||||
this.map.delete(key)
|
||||
}
|
||||
this.map.set(key, value);
|
||||
return pre;
|
||||
} catch (e) {
|
||||
throw new Error('put value error');
|
||||
} finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
// 去除键值,(去除键数据中的键名及对应的值)
|
||||
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()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue