业务模块并发加载场景
在应用启动时,多个业务模块需要加载,例如地图应用中的定位、打车、导航等模块。如果全部在UI主线程初始化,会严重影响应用冷启动时间。此时,应在不同子线程中并行加载这些模块,以降低启动耗时。
通过使用ArkTS提供的TaskPool能力,可以将不同的业务初始化任务移到子线程中。业务模块可通过下沉C++实现为NativeBinding对象或在ArkTS层定义为Sendable对象,从而将初始化的模块返回给UI主线程调用,实现如下。
-
各业务功能(SDK)模块定义(这里以使用Sendable对象为例)。
计算器业务模块定义如下:
import { collections } from '@kit.ArkTS';@Sendableexport class Calculator {public history?: collections.Array<collections.Array<string>>;public totalCount: number = 0;// 初始化static init(): Calculator {let calc = new Calculator();calc.totalCount = 0;calc.history = collections.Array.create(calc.totalCount, collections.Array.create(2, ''));return calc;}// 加法运算add(a: number, b: number) {let result = a + b;this.newCalc(`${a} + ${b}`, `${result}`);return result;}// 减法运算sub(a: number, b: number) {let result = a - b;this.newCalc(`${a} - ${b}`, `${result}`);return result;}// 乘法运算mul(a: number, b: number) {let result = a * b;this.newCalc(`${a} * ${b}`, `${result}`);return result;}// 除法运算div(a: number, b: number) {let result = a / b;this.newCalc(`${a} / ${b}`, `${result}`);return result;}// 获取历史记录getHistory(): collections.Array<collections.Array<string>> {return this.history!;}// 打印历史记录showHistory() {for (let i = 0; i < this.totalCount; i++) {console.info(`${i}: ${this.history![i][0]} = ${this.history![i][1]}`);}}// 添加新计算记录private newCalc(opt: string, ret: string) {let newRecord = new collections.Array<string>(opt, ret);this.totalCount = this.history!.unshift(newRecord);}}定时器业务模块的定义如下:
@Sendableexport class TimerSdk {// 初始化static init(): TimerSdk {let timer = new TimerSdk();return timer;}// 倒计时async Countdown(time: number) {return new Promise((resolve: (value: boolean) => void) => {setTimeout(() => {resolve(true);}, time);});}} -
在UI主线程触发各业务模块分发到子线程,加载完成后在UI主线程使用,示例如下:
import { Calculator } from '../sdk/Calculator';import { TimerSdk } from '../sdk/TimerSdk';import { taskpool } from '@kit.ArkTS';// 初始化Calculator@Concurrentfunction initCalculator(): Calculator {return Calculator.init();}// 初始化TimerSdk@Concurrentfunction initTimerSdk(): TimerSdk {return TimerSdk.init();}@Entry@Componentstruct Index {@State calculateAdd: string = 'calculate add';@State showHistory: string = 'show history';@State countdown: string = 'countdown';calc?: Calculator;timer?: TimerSdk;aboutToAppear(): void {taskpool.execute(initCalculator).then((ret) => {this.calc = ret as Calculator;})taskpool.execute(initTimerSdk).then((ret) => {this.timer = ret as TimerSdk;})}build() {Row() {Column() {Text(this.calculateAdd).id('add').fontSize(50).fontWeight(FontWeight.Bold).alignRules({center: { anchor: '__container__', align: VerticalAlign.Center },middle: { anchor: '__container__', align: HorizontalAlign.Center }}).onClick(async () => {let result = this.calc?.add(1, 2)console.info(`Result is ${result}`)this.calculateAdd = 'success';})Text(this.showHistory).id('show').fontSize(50).fontWeight(FontWeight.Bold).alignRules({center: { anchor: '__container__', align: VerticalAlign.Center },middle: { anchor: '__container__', align: HorizontalAlign.Center }}).onClick(async () => {this.calc?.showHistory();this.showHistory = 'success';})Text(this.countdown).id('get').fontSize(50).fontWeight(FontWeight.Bold).alignRules({center: { anchor: '__container__', align: VerticalAlign.Center },middle: { anchor: '__container__', align: HorizontalAlign.Center }}).onClick(async () => {console.info(`Timer start`);await this.timer?.Countdown(1000);console.info(`Timer end`);this.countdown = 'success';})}.width('100%')}.height('100%')}}