• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Concurrent Loading of Service Modules
2
3During application launch, multiple service modules need to be loaded. For example, in a mapping application, different modules such as positioning, ride-hailing, and navigation are required. Initializing all these modules in the UI main thread can significantly increase the cold start time. To address this, these modules should be loaded concurrently in separate background threads to reduce launch latency.
4
5By leveraging the TaskPool capabilities provided by ArkTS, different service initialization tasks can be offloaded to background threads. Service modules can be implemented in C++ as [NativeBinding objects](transferabled-object.md) or defined in ArkTS as [Sendable objects](arkts-sendable.md). The initialized modules can then be returned to the UI main thread for use. The implementation involves the following steps:
6
71. Define each service module (SDK) (using Sendable objects as an example).
8
9   Define the calculator service module as follows:
10
11   ```ts
12   // sdk/Calculator.ets
13   import { collections } from '@kit.ArkTS'
14
15   @Sendable
16   export class Calculator {
17     history?: collections.Array<collections.Array<string>>
18     totalCount: number = 0
19
20     static init(): Calculator {
21       let calc = new Calculator()
22       calc.totalCount = 0
23       calc.history = collections.Array.create(calc.totalCount, collections.Array.create(2, ""));
24       return calc
25     }
26
27     add(a: number, b: number) {
28       let result = a + b;
29       this.newCalc(`${a} + ${b}`, `${result}`);
30       return result
31     }
32
33     sub(a: number, b: number) {
34       let result = a - b;
35       this.newCalc(`${a} - ${b}`, `${result}`);
36       return result
37     }
38
39     mul(a: number, b: number) {
40       let result = a * b;
41       this.newCalc(`${a} * ${b}`, `${result}`);
42       return result
43     }
44
45     div(a: number, b: number) {
46       let result = a / b;
47       this.newCalc(`${a} / ${b}`, `${result}`);
48       return result
49     }
50
51     getHistory(): collections.Array<collections.Array<string>> {
52       return this.history!;
53     }
54
55     showHistory() {
56       for (let i = 0; i < this.totalCount; i++) {
57         console.info(`${i}: ${this.history![i][0]} = ${this.history![i][1]}`)
58       }
59     }
60
61     private newCalc(opt: string, ret: string) {
62       let newRecord = new collections.Array<string>(opt, ret)
63       this.totalCount = this.history!.unshift(newRecord)
64     }
65   }
66   ```
67
68   Define the timer service module as follows:
69
70   ```ts
71   // sdk/TimerSdk.ets
72   @Sendable
73   export class TimerSdk {
74     static init(): TimerSdk {
75       let timer = new TimerSdk()
76       return timer
77     }
78
79     async Countdown(time: number) {
80       return new Promise((resolve: (value: boolean) => void) => {
81         setTimeout(() => {
82           resolve(true)
83         }, time)
84       })
85     }
86   }
87   ```
88
892. In the UI main thread, trigger the distribution of service modules to child threads, and use them in the UI main thread after loading is complete. The following is an example:
90
91   ```ts
92   // Index.ets
93   import { Calculator } from '../sdk/Calculator'
94   import { TimerSdk } from '../sdk/TimerSdk'
95   import { taskpool } from '@kit.ArkTS';
96
97   @Concurrent
98   function initCalculator(): Calculator {
99     return Calculator.init()
100   }
101
102   @Concurrent
103   function initTimerSdk(): TimerSdk {
104     return TimerSdk.init()
105   }
106
107   @Entry
108   @Component
109   struct Index {
110     calc?: Calculator
111     timer?: TimerSdk
112
113     aboutToAppear(): void {
114       taskpool.execute(initCalculator).then((ret) => {
115         this.calc = ret as Calculator
116       })
117       taskpool.execute(initTimerSdk).then((ret) => {
118         this.timer = ret as TimerSdk
119       })
120     }
121
122     build() {
123       Row() {
124         Column() {
125           Text("calculate add")
126             .id('add')
127             .fontSize(50)
128             .fontWeight(FontWeight.Bold)
129             .alignRules({
130               center: { anchor: '__container__', align: VerticalAlign.Center },
131               middle: { anchor: '__container__', align: HorizontalAlign.Center }
132             })
133             .onClick(async () => {
134               let result = this.calc?.add(1, 2)
135               console.info(`Result is ${result}`)
136             })
137           Text("show history")
138             .id('show')
139             .fontSize(50)
140             .fontWeight(FontWeight.Bold)
141             .alignRules({
142               center: { anchor: '__container__', align: VerticalAlign.Center },
143               middle: { anchor: '__container__', align: HorizontalAlign.Center }
144             })
145             .onClick(async () => {
146               this.calc?.showHistory()
147             })
148           Text("countdown")
149             .id('get')
150             .fontSize(50)
151             .fontWeight(FontWeight.Bold)
152             .alignRules({
153               center: { anchor: '__container__', align: VerticalAlign.Center },
154               middle: { anchor: '__container__', align: HorizontalAlign.Center }
155             })
156             .onClick(async () => {
157               console.info(`Timer start`)
158               await this.timer?.Countdown(1000);
159               console.info(`Timer end`)
160             })
161         }
162         .width('100%')
163       }
164       .height('100%')
165     }
166   }
167   ```
168