王士厅

fix: 图集使用taskpool任务池优化图片加载、下载逻辑

... ... @@ -11,6 +11,8 @@ import { TrackConstants, TrackingButton } from 'wdTracking';
import { faceDetector } from '@kit.CoreVisionKit';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
import fileIo from '@ohos.file.fs';
import { httpRequest } from '../utils/httpRequest';
import { taskpool } from '@kit.ArkTS';
const PERMISSIONS: Array<Permissions> = [
'ohos.permission.READ_IMAGEVIDEO',
... ... @@ -21,6 +23,23 @@ const PERMISSIONS: Array<Permissions> = [
* saveButton参考文档
* https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/savebutton-0000001820999677
* */
@Concurrent
async function getPicture(imageUrl: string): Promise<ArrayBuffer> {
let ret: ArrayBuffer = await new Promise((resolve, reject) => {
httpRequest.httpRequestInStream(imageUrl, (res: ArrayBuffer) => {
resolve(res); // 成功时解析Promise
}, () => {
// 下载失败时弹窗提示检查网络
promptAction.showToast({
message: $r('app.string.image_request_fail'),
duration: 2000
});
reject(new Error('Image download failed')); // 失败时拒绝Promise
});
});
return ret
}
@Component
export struct ImageDownloadComponent {
@State image: PixelMap | undefined = undefined;
... ... @@ -79,61 +98,12 @@ export struct ImageDownloadComponent {
const context = getContext(this) as common.UIAbilityContext;
const atManager = abilityAccessCtrl.createAtManager();
await atManager.requestPermissionsFromUser(context, PERMISSIONS);
this.getPicture();
}
/**
* 通过http的request方法从网络下载图片资源
*/
async getPicture() {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头事件
httpRequest.on('headersReceive', (header: Object) => {
//console.info('header: ' + JSON.stringify(header));
});
// 用于订阅HTTP流式响应数据接收事件
let res = new ArrayBuffer(0);
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
const resView = new Uint8Array(newRes);
resView.set(new Uint8Array(res));
resView.set(new Uint8Array(data), res.byteLength);
res = newRes;
// //console.info('dataReceive res length: ' + res.byteLength);
});
// 用于订阅HTTP流式响应数据接收完毕事件
httpRequest.on('dataEnd', () => {
this.transcodePixelMap(res);
// 判断网络获取到的资源是否为ArrayBuffer类型
//console.info(`dataEnd getPicture ${res}`)
if (res instanceof ArrayBuffer) {
//console.info(`dataEnd getPicture`)
this.imageBuffer = res as ArrayBuffer;
}
//console.info('No more data in response, data receive end');
});
httpRequest.requestInStream(this.url,
(error: BusinessError, data: number) => {
if (error) {
// 下载失败时弹窗提示检查网络,不执行后续逻辑
promptAction.showToast({
message: $r('app.string.image_request_fail'),
duration: 2000
// 通过任务池(taskpool)从网络下载图片资源
taskpool.execute(getPicture, this.url).then((res) => {
const imgBuffer = res as ArrayBuffer
this.imageBuffer = imgBuffer;
this.transcodePixelMap(imgBuffer);
})
//console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
return;
}
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 取消订阅HTTP流式响应数据接收事件
httpRequest.off('dataReceive');
// 取消订阅HTTP流式响应数据接收完毕事件
httpRequest.off('dataEnd');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
)
}
/**
... ...
... ... @@ -6,11 +6,29 @@ import { OffsetModel } from '../model/OffsetModel';
import { WindowSizeManager } from '../utils/Managers';
import { runWithAnimation } from '../utils/FuncUtils';
import { PhotoListBean } from 'wdBean/Index';
import { http } from '@kit.NetworkKit';
import { router } from '@kit.ArkUI';
import { taskpool } from '@kit.ArkTS';
import { httpRequest } from '../utils/httpRequest';
const TAG = 'MultiPictureDetailItemComponent';
@Concurrent
async function getPicture(imageUrl: string): Promise<ArrayBuffer> {
let ret: ArrayBuffer = await new Promise((resolve, reject) => {
httpRequest.httpRequestInStream(imageUrl, (res: ArrayBuffer) => {
resolve(res); // 成功时解析Promise
}, () => {
// 下载失败时弹窗提示检查网络
promptAction.showToast({
message: $r('app.string.image_request_fail'),
duration: 2000
});
reject(new Error('Image download failed')); // 失败时拒绝Promise
});
});
return ret
}
@Reusable
@Component
export struct MultiPictureDetailItemComponent {
... ... @@ -34,65 +52,17 @@ export struct MultiPictureDetailItemComponent {
windowSizeManager: WindowSizeManager = new WindowSizeManager();
async aboutToAppear() {
aboutToAppear() {
this.imageUri = this.MultiPictureDetailItem.picPath
this.getPicture()
}
/**
* 通过http的request方法从网络下载图片资源
*/
async getPicture() {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头事件
httpRequest.on('headersReceive', (header: Object) => {
console.info('header: ' + JSON.stringify(header));
});
// 用于订阅HTTP流式响应数据接收事件
let res = new ArrayBuffer(0);
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
const resView = new Uint8Array(newRes);
resView.set(new Uint8Array(res));
resView.set(new Uint8Array(data), res.byteLength);
res = newRes;
// console.info('dataReceive res length: ' + res.byteLength);
});
// 用于订阅HTTP流式响应数据接收完毕事件
httpRequest.on('dataEnd', () => {
this.transcodePixelMap(res);
// 判断网络获取到的资源是否为ArrayBuffer类型
console.info(`dataEnd getPicture ${res}`)
if (res instanceof ArrayBuffer) {
console.info(`dataEnd getPicture`)
this.imageBuffer = res as ArrayBuffer;
}
console.info('No more data in response, data receive end');
});
httpRequest.requestInStream(this.imageUri,
(error: BusinessError, data: number) => {
if (error) {
// 下载失败时弹窗提示检查网络,不执行后续逻辑
promptAction.showToast({
message: $r('app.string.image_request_fail'),
duration: 2000
// 通过任务池(taskpool)从网络下载图片资源
taskpool.execute(getPicture, this.imageUri).then((res) => {
const imgBuffer = res as ArrayBuffer
this.imageBuffer = imgBuffer;
this.transcodePixelMap(imgBuffer);
})
console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
return;
}
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 取消订阅HTTP流式响应数据接收事件
httpRequest.off('dataReceive');
// 取消订阅HTTP流式响应数据接收完毕事件
httpRequest.off('dataEnd');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
)
}
/**
* 使用createPixelMap将ArrayBuffer类型的图片装换为PixelMap类型
* @param data:网络获取到的资源
... ...
import { http } from '@kit.NetworkKit';
const TAG = 'httpRequestInStream'
export class httpRequest {
// 大于5M的下载请求,使用流下载
/**
* 发起HTTP请求以下载图片资源
* @param {string} imageUrl 图片的URL
* @param {Function} onSuccess 成功回调函数
* @param {Function} onError 失败回调函数
*/
public static httpRequestInStream(imageUrl:string, onSuccess:Function, onError:Function) {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
const httpRequest = http.createHttp();
// 订阅HTTP响应头事件
httpRequest.on('headersReceive', (header) => {
// console.info('header: ' + JSON.stringify(header));
});
// 用于订阅HTTP流式响应数据接收事件
let res = new ArrayBuffer(0);
httpRequest.on('dataReceive', (data) => {
const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
const resView = new Uint8Array(newRes);
resView.set(new Uint8Array(res));
resView.set(new Uint8Array(data), res.byteLength);
res = newRes;
// console.info(TAG, 'dataReceive res length: ' + res.byteLength);
});
// 用于订阅HTTP流式响应数据接收完毕事件
httpRequest.on('dataEnd', () => {
if (res instanceof ArrayBuffer) {
// 如果成功,调用onSuccess回调
// console.info(TAG, 'Success in response, data receive end');
onSuccess(res);
} else {
// 如果数据不是ArrayBuffer类型,可以在这里处理异常
// console.error(TAG, 'Unexpected data type:', res);
onError(new Error('Data is not an ArrayBuffer'));
}
// console.info(TAG, 'No more data in response, data receive end');
});
httpRequest.requestInStream(imageUrl, (error, data) => {
if (error) {
// 如果发生错误,取消订阅事件并销毁请求对象
httpRequest.off('headersReceive');
httpRequest.off('dataReceive');
httpRequest.off('dataEnd');
httpRequest.destroy();
// console.error(`http request failed with. Code: ${error.code}, message: ${error.message}`);
// 调用onError回调
onError(error);
return;
}
// 取消订阅事件
httpRequest.off('headersReceive');
httpRequest.off('dataReceive');
httpRequest.off('dataEnd');
// 销毁请求对象
httpRequest.destroy();
});
}
}
\ No newline at end of file
... ...