主线程启动文件上传、下载、持久化等耗时操作时,往往都需要通过子线程完成相关操作,为了让UI体验更好,文件下载或者报错的过程中往往都需要提供进度条提示以提升用户感知。同时对于文件列表类型的上传、下载往往还会提供类似暂停\继续的能力,类似如下场景:
本案例将使用Sendable共享对象实现以下两个主要功能:
1、子线程的计算结果刷新UI(进度通知、下载结果通知)。
2、主线程控制子线程业务逻辑(暂停下载、接续下载)。
方案介绍
-
通过Sendable构建可跨线程共享的对象DownloadVideoInfo;
-
主线程通过构建new taskpool.Task(downloadVideo, this.dvi)将DownloadVideoInfo共享对象同步给子线程(this.dvi是DownloadVideoInfo对象实例,downloadVideo是通过@Concurrent修饰的多线程任务);
-
当点击启动时,通过taskpool.execute()方法启动子线程;
-
主线程通过的onReceiveData()注册下载进度更新回调,已实现下载进度的UI刷新。
-
子线程在共享对象中更新下载进度,并通过taskpool.Task.sendData("UPDATE_DOWNLOAD_PROGRESS")通知主线程从共享对象中更新下载进度。
-
主线程通过this.downloadTask.onReceiveData()方法注册子线程发送来的消息回调,此处通过监听"UPDATE_DOWNLOAD_PROGRESS"消息,实现UI进度条更新。
-
-
下载命令控制,暂停/继续下载时需要通过主线程想子线程发送消息,由于taskpool不支持该能力,因此通过共享对象实现此能力。
核心代码
Step1:构建@Sendable对象DownloadVideoInfo、VideoInfo、ActorInfo。此处需要注意,DownloadCommandEnum枚举需要使用const进行修饰。
-
DownloadVideoInfo共享类中,使用了基础类型和其他共享对象作为属性,并携带成员方法。
// src\main\ets\model\DownloadVideoInfo.ets
import { DownloadStateEnum } from './DownloadStateEnum';
import { VideoInfo } from './VideoInfo';
@Sendable
export class DownloadVideoInfo {
videoUrl: string = "URL";
downloadProgress: number = 0;
command: DownloadCommandEnum = DownloadCommandEnum.CONTINUE_DOWNLOADING;
videoInfo : VideoInfo = new VideoInfo();
constructor(videoUrl : string) {
this.videoUrl = videoUrl;
}
getDownloadProgress(): number {
return this.downloadProgress