王士厅

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

@@ -11,6 +11,8 @@ import { TrackConstants, TrackingButton } from 'wdTracking'; @@ -11,6 +11,8 @@ import { TrackConstants, TrackingButton } from 'wdTracking';
11 import { faceDetector } from '@kit.CoreVisionKit'; 11 import { faceDetector } from '@kit.CoreVisionKit';
12 import mediaLibrary from '@ohos.multimedia.mediaLibrary'; 12 import mediaLibrary from '@ohos.multimedia.mediaLibrary';
13 import fileIo from '@ohos.file.fs'; 13 import fileIo from '@ohos.file.fs';
  14 +import { httpRequest } from '../utils/httpRequest';
  15 +import { taskpool } from '@kit.ArkTS';
14 16
15 const PERMISSIONS: Array<Permissions> = [ 17 const PERMISSIONS: Array<Permissions> = [
16 'ohos.permission.READ_IMAGEVIDEO', 18 'ohos.permission.READ_IMAGEVIDEO',
@@ -21,6 +23,23 @@ const PERMISSIONS: Array<Permissions> = [ @@ -21,6 +23,23 @@ const PERMISSIONS: Array<Permissions> = [
21 * saveButton参考文档 23 * saveButton参考文档
22 * https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/savebutton-0000001820999677 24 * https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/savebutton-0000001820999677
23 * */ 25 * */
  26 +@Concurrent
  27 +async function getPicture(imageUrl: string): Promise<ArrayBuffer> {
  28 + let ret: ArrayBuffer = await new Promise((resolve, reject) => {
  29 + httpRequest.httpRequestInStream(imageUrl, (res: ArrayBuffer) => {
  30 + resolve(res); // 成功时解析Promise
  31 + }, () => {
  32 + // 下载失败时弹窗提示检查网络
  33 + promptAction.showToast({
  34 + message: $r('app.string.image_request_fail'),
  35 + duration: 2000
  36 + });
  37 + reject(new Error('Image download failed')); // 失败时拒绝Promise
  38 + });
  39 + });
  40 + return ret
  41 +}
  42 +
24 @Component 43 @Component
25 export struct ImageDownloadComponent { 44 export struct ImageDownloadComponent {
26 @State image: PixelMap | undefined = undefined; 45 @State image: PixelMap | undefined = undefined;
@@ -79,61 +98,12 @@ export struct ImageDownloadComponent { @@ -79,61 +98,12 @@ export struct ImageDownloadComponent {
79 const context = getContext(this) as common.UIAbilityContext; 98 const context = getContext(this) as common.UIAbilityContext;
80 const atManager = abilityAccessCtrl.createAtManager(); 99 const atManager = abilityAccessCtrl.createAtManager();
81 await atManager.requestPermissionsFromUser(context, PERMISSIONS); 100 await atManager.requestPermissionsFromUser(context, PERMISSIONS);
82 - this.getPicture();  
83 - }  
84 -  
85 - /**  
86 - * 通过http的request方法从网络下载图片资源  
87 - */  
88 - async getPicture() {  
89 - // 每一个httpRequest对应一个HTTP请求任务,不可复用  
90 - let httpRequest = http.createHttp();  
91 - // 用于订阅HTTP响应头事件  
92 - httpRequest.on('headersReceive', (header: Object) => {  
93 - //console.info('header: ' + JSON.stringify(header));  
94 - });  
95 - // 用于订阅HTTP流式响应数据接收事件  
96 - let res = new ArrayBuffer(0);  
97 - httpRequest.on('dataReceive', (data: ArrayBuffer) => {  
98 - const newRes = new ArrayBuffer(res.byteLength + data.byteLength);  
99 - const resView = new Uint8Array(newRes);  
100 - resView.set(new Uint8Array(res));  
101 - resView.set(new Uint8Array(data), res.byteLength);  
102 - res = newRes;  
103 - // //console.info('dataReceive res length: ' + res.byteLength);  
104 - });  
105 - // 用于订阅HTTP流式响应数据接收完毕事件  
106 - httpRequest.on('dataEnd', () => {  
107 - this.transcodePixelMap(res);  
108 - // 判断网络获取到的资源是否为ArrayBuffer类型  
109 - //console.info(`dataEnd getPicture ${res}`)  
110 - if (res instanceof ArrayBuffer) {  
111 - //console.info(`dataEnd getPicture`)  
112 - this.imageBuffer = res as ArrayBuffer;  
113 - }  
114 - //console.info('No more data in response, data receive end');  
115 - });  
116 - httpRequest.requestInStream(this.url,  
117 - (error: BusinessError, data: number) => {  
118 - if (error) {  
119 - // 下载失败时弹窗提示检查网络,不执行后续逻辑  
120 - promptAction.showToast({  
121 - message: $r('app.string.image_request_fail'),  
122 - duration: 2000  
123 - })  
124 - //console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);  
125 - return;  
126 - }  
127 - // 取消订阅HTTP响应头事件  
128 - httpRequest.off('headersReceive');  
129 - // 取消订阅HTTP流式响应数据接收事件  
130 - httpRequest.off('dataReceive');  
131 - // 取消订阅HTTP流式响应数据接收完毕事件  
132 - httpRequest.off('dataEnd');  
133 - // 当该请求使用完毕时,调用destroy方法主动销毁  
134 - httpRequest.destroy();  
135 - }  
136 - ) 101 + // 通过任务池(taskpool)从网络下载图片资源
  102 + taskpool.execute(getPicture, this.url).then((res) => {
  103 + const imgBuffer = res as ArrayBuffer
  104 + this.imageBuffer = imgBuffer;
  105 + this.transcodePixelMap(imgBuffer);
  106 + })
137 } 107 }
138 108
139 /** 109 /**
@@ -6,11 +6,29 @@ import { OffsetModel } from '../model/OffsetModel'; @@ -6,11 +6,29 @@ import { OffsetModel } from '../model/OffsetModel';
6 import { WindowSizeManager } from '../utils/Managers'; 6 import { WindowSizeManager } from '../utils/Managers';
7 import { runWithAnimation } from '../utils/FuncUtils'; 7 import { runWithAnimation } from '../utils/FuncUtils';
8 import { PhotoListBean } from 'wdBean/Index'; 8 import { PhotoListBean } from 'wdBean/Index';
9 -import { http } from '@kit.NetworkKit';  
10 import { router } from '@kit.ArkUI'; 9 import { router } from '@kit.ArkUI';
  10 +import { taskpool } from '@kit.ArkTS';
  11 +import { httpRequest } from '../utils/httpRequest';
11 12
12 const TAG = 'MultiPictureDetailItemComponent'; 13 const TAG = 'MultiPictureDetailItemComponent';
13 14
  15 +@Concurrent
  16 +async function getPicture(imageUrl: string): Promise<ArrayBuffer> {
  17 + let ret: ArrayBuffer = await new Promise((resolve, reject) => {
  18 + httpRequest.httpRequestInStream(imageUrl, (res: ArrayBuffer) => {
  19 + resolve(res); // 成功时解析Promise
  20 + }, () => {
  21 + // 下载失败时弹窗提示检查网络
  22 + promptAction.showToast({
  23 + message: $r('app.string.image_request_fail'),
  24 + duration: 2000
  25 + });
  26 + reject(new Error('Image download failed')); // 失败时拒绝Promise
  27 + });
  28 + });
  29 + return ret
  30 +}
  31 +
14 @Reusable 32 @Reusable
15 @Component 33 @Component
16 export struct MultiPictureDetailItemComponent { 34 export struct MultiPictureDetailItemComponent {
@@ -34,64 +52,16 @@ export struct MultiPictureDetailItemComponent { @@ -34,64 +52,16 @@ export struct MultiPictureDetailItemComponent {
34 windowSizeManager: WindowSizeManager = new WindowSizeManager(); 52 windowSizeManager: WindowSizeManager = new WindowSizeManager();
35 53
36 54
37 - async aboutToAppear() { 55 + aboutToAppear() {
38 this.imageUri = this.MultiPictureDetailItem.picPath 56 this.imageUri = this.MultiPictureDetailItem.picPath
39 - this.getPicture() 57 + // 通过任务池(taskpool)从网络下载图片资源
  58 + taskpool.execute(getPicture, this.imageUri).then((res) => {
  59 + const imgBuffer = res as ArrayBuffer
  60 + this.imageBuffer = imgBuffer;
  61 + this.transcodePixelMap(imgBuffer);
  62 + })
40 } 63 }
41 64
42 - /**  
43 - * 通过http的request方法从网络下载图片资源  
44 - */  
45 - async getPicture() {  
46 - // 每一个httpRequest对应一个HTTP请求任务,不可复用  
47 - let httpRequest = http.createHttp();  
48 - // 用于订阅HTTP响应头事件  
49 - httpRequest.on('headersReceive', (header: Object) => {  
50 - console.info('header: ' + JSON.stringify(header));  
51 - });  
52 - // 用于订阅HTTP流式响应数据接收事件  
53 - let res = new ArrayBuffer(0);  
54 - httpRequest.on('dataReceive', (data: ArrayBuffer) => {  
55 - const newRes = new ArrayBuffer(res.byteLength + data.byteLength);  
56 - const resView = new Uint8Array(newRes);  
57 - resView.set(new Uint8Array(res));  
58 - resView.set(new Uint8Array(data), res.byteLength);  
59 - res = newRes;  
60 - // console.info('dataReceive res length: ' + res.byteLength);  
61 - });  
62 - // 用于订阅HTTP流式响应数据接收完毕事件  
63 - httpRequest.on('dataEnd', () => {  
64 - this.transcodePixelMap(res);  
65 - // 判断网络获取到的资源是否为ArrayBuffer类型  
66 - console.info(`dataEnd getPicture ${res}`)  
67 - if (res instanceof ArrayBuffer) {  
68 - console.info(`dataEnd getPicture`)  
69 - this.imageBuffer = res as ArrayBuffer;  
70 - }  
71 - console.info('No more data in response, data receive end');  
72 - });  
73 - httpRequest.requestInStream(this.imageUri,  
74 - (error: BusinessError, data: number) => {  
75 - if (error) {  
76 - // 下载失败时弹窗提示检查网络,不执行后续逻辑  
77 - promptAction.showToast({  
78 - message: $r('app.string.image_request_fail'),  
79 - duration: 2000  
80 - })  
81 - console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);  
82 - return;  
83 - }  
84 - // 取消订阅HTTP响应头事件  
85 - httpRequest.off('headersReceive');  
86 - // 取消订阅HTTP流式响应数据接收事件  
87 - httpRequest.off('dataReceive');  
88 - // 取消订阅HTTP流式响应数据接收完毕事件  
89 - httpRequest.off('dataEnd');  
90 - // 当该请求使用完毕时,调用destroy方法主动销毁  
91 - httpRequest.destroy();  
92 - }  
93 - )  
94 - }  
95 65
96 /** 66 /**
97 * 使用createPixelMap将ArrayBuffer类型的图片装换为PixelMap类型 67 * 使用createPixelMap将ArrayBuffer类型的图片装换为PixelMap类型
  1 +import { http } from '@kit.NetworkKit';
  2 +
  3 +const TAG = 'httpRequestInStream'
  4 +export class httpRequest {
  5 + // 大于5M的下载请求,使用流下载
  6 + /**
  7 + * 发起HTTP请求以下载图片资源
  8 + * @param {string} imageUrl 图片的URL
  9 + * @param {Function} onSuccess 成功回调函数
  10 + * @param {Function} onError 失败回调函数
  11 + */
  12 + public static httpRequestInStream(imageUrl:string, onSuccess:Function, onError:Function) {
  13 + // 每一个httpRequest对应一个HTTP请求任务,不可复用
  14 + const httpRequest = http.createHttp();
  15 +
  16 + // 订阅HTTP响应头事件
  17 + httpRequest.on('headersReceive', (header) => {
  18 + // console.info('header: ' + JSON.stringify(header));
  19 + });
  20 +
  21 + // 用于订阅HTTP流式响应数据接收事件
  22 + let res = new ArrayBuffer(0);
  23 +
  24 + httpRequest.on('dataReceive', (data) => {
  25 + const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
  26 + const resView = new Uint8Array(newRes);
  27 + resView.set(new Uint8Array(res));
  28 + resView.set(new Uint8Array(data), res.byteLength);
  29 + res = newRes;
  30 + // console.info(TAG, 'dataReceive res length: ' + res.byteLength);
  31 + });
  32 +
  33 + // 用于订阅HTTP流式响应数据接收完毕事件
  34 + httpRequest.on('dataEnd', () => {
  35 + if (res instanceof ArrayBuffer) {
  36 + // 如果成功,调用onSuccess回调
  37 + // console.info(TAG, 'Success in response, data receive end');
  38 + onSuccess(res);
  39 + } else {
  40 + // 如果数据不是ArrayBuffer类型,可以在这里处理异常
  41 + // console.error(TAG, 'Unexpected data type:', res);
  42 + onError(new Error('Data is not an ArrayBuffer'));
  43 + }
  44 + // console.info(TAG, 'No more data in response, data receive end');
  45 + });
  46 +
  47 + httpRequest.requestInStream(imageUrl, (error, data) => {
  48 + if (error) {
  49 + // 如果发生错误,取消订阅事件并销毁请求对象
  50 + httpRequest.off('headersReceive');
  51 + httpRequest.off('dataReceive');
  52 + httpRequest.off('dataEnd');
  53 + httpRequest.destroy();
  54 + // console.error(`http request failed with. Code: ${error.code}, message: ${error.message}`);
  55 + // 调用onError回调
  56 + onError(error);
  57 + return;
  58 + }
  59 +
  60 + // 取消订阅事件
  61 + httpRequest.off('headersReceive');
  62 + httpRequest.off('dataReceive');
  63 + httpRequest.off('dataEnd');
  64 +
  65 + // 销毁请求对象
  66 + httpRequest.destroy();
  67 + });
  68 + }
  69 +}