1# AppStartup
2
3
4## Overview
5
6During application initialization, a series of startup tasks are triggered. If these tasks are concentratedly placed within the [onCreate](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityoncreate) lifecycle of the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) of the application's main module ([module](../quick-start/application-package-overview.md#module-types) of the entry type), they must be executed sequentially on the main thread, which significantly affects the application launch speed. In addition, when there are too many tasks, complex dependencies between them make the code difficult to maintain.
7
8AppStartup offers an efficient approach to application initialization. By enabling the asynchronous initiation of startup tasks, it ensures a smoother startup process. The centralized configuration of task execution order and interdependencies in a single file simplifies and clarifies the startup codebase, enhancing maintainability.
9
10AppStartup supports startup tasks in automatic or manual mode. By default, the automatic mode is used. After an [AbilityStage](../reference/apis-ability-kit/js-apis-app-ability-abilityStage.md) is created, the configured startup tasks are loaded and executed in automatic mode. You can also call [startupManager.run](../reference/apis-ability-kit/js-apis-app-appstartup-startupManager.md#startupmanagerrun) to execute the startup tasks in manual mode after a UIAbility is created.
11
12**Figure 1** Startup procedure
13
14![app-startup-procedure](figures/app-startup-procedure.png)
15
16## Constraints
17
18- AppStartup can be used only in entry [modules](../quick-start/application-package-overview.md#module-types).
19
20- Circular dependencies are not allowed between startup tasks.
21
22## Development Process
23
241. [Defining an AppStartup Configuration File](#defining-an-appstartup-configuration-file): Create an AppStartup configuration file in the resource file directory, add the configuration about startup tasks, and reference the configuration file in [module.json5](../quick-start/module-configuration-file.md).
252. [Setting Startup Parameters](#setting-startup-parameters): In the startup parameter file, set parameters such as the timeout interval and startup task listener.
263. [Adding a Startup Task for Each Component to Be Initialized](#adding-a-startup-task-for-each-component-to-be-initialized): Implement the [StartupTask](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md) interface.
27
28## How to Develop
29
30### Defining an AppStartup Configuration File
31
321. Create a AppStartup configuration file in the **resources/base/profile** directory of the application's main module ([module](../quick-start/application-package-overview.md#module-types) of the entry type). The file name can be customized. The following uses **startup_config.json** as an example.
33
342. In the **startup_config.json** file, add the configuration for each startup task in sequence.
35
36    It is assumed that the application has six startup tasks. The dependencies between the tasks are shown in the figure below. To facilitate concurrent execution of startup tasks, a startup task file should contain only one startup task. In this example, each startup task corresponds to a startup task file.
37
38    **Figure 2** Dependencies between startup tasks
39    
40    ![app-startup](figures/app-startup.png) 
41    
42    1. In the **ets/startup** directory, create six startup task files and a common startup parameter file. The file names must be unique.
43    
44        1. Create six startup task files. In this example, the six files are named from **StartupTask_001.ets** to **StartupTask_006.ets**.
45        2. Create a startup parameter file. In this example, the file name is **StartupConfig.ets**.
46        
47    2. Add the information about the startup task files and startup parameter file to the **startup_config.json** file.
48    
49        The following is an example of the **startup_config.json** file:
50        
51        ```json
52        {
53          "startupTasks": [
54            {
55              "name": "StartupTask_001",
56              "srcEntry": "./ets/startup/StartupTask_001.ets",
57              "dependencies": [
58                "StartupTask_002",
59                "StartupTask_003"
60              ],
61              "runOnThread": "taskPool",
62              "waitOnMainThread": false
63            },
64            {
65              "name": "StartupTask_002",
66              "srcEntry": "./ets/startup/StartupTask_002.ets",
67              "dependencies": [
68                "StartupTask_004"
69              ],
70              "runOnThread": "taskPool",
71              "waitOnMainThread": false
72            },
73            {
74              "name": "StartupTask_003",
75              "srcEntry": "./ets/startup/StartupTask_003.ets",
76              "dependencies": [
77                "StartupTask_004"
78              ],
79              "runOnThread": "taskPool",
80              "waitOnMainThread": false
81            },
82            {
83              "name": "StartupTask_004",
84              "srcEntry": "./ets/startup/StartupTask_004.ets",
85              "runOnThread": "taskPool",
86              "waitOnMainThread": false
87            },
88            {
89              "name": "StartupTask_005",
90              "srcEntry": "./ets/startup/StartupTask_005.ets",
91              "dependencies": [
92                "StartupTask_006"
93              ],
94              "runOnThread": "mainThread",
95              "waitOnMainThread": true,
96              "excludeFromAutoStart": true
97            },
98            {
99              "name": "StartupTask_006",
100              "srcEntry": "./ets/startup/StartupTask_006.ets",
101              "runOnThread": "mainThread",
102              "waitOnMainThread": false,
103              "excludeFromAutoStart": true
104            }
105          ],
106          "configEntry": "./ets/startup/StartupConfig.ets"
107        }
108        ```
109    
110        **Table 1** Fields in the startup_config.json file
111
112        | Field| Description| Data Type| Default Value Allowed|
113        | -------- | -------- | -------- | -------- |
114        | startupTasks | Configuration about the startup tasks. For details, see the following table.| Object array| No|
115        | configEntry | Path of the startup parameter file.| String| No|
116        
117        
118        **Table 2** Description of startupTasks
119
120        | Field| Description| Data Type| Default Value Allowed|
121        | -------- | -------- | -------- | -------- |
122        | name | Class name of the startup task.| String| No|
123        | srcEntry | Path of the file corresponding to the startup task.| String| No|
124        | dependencies | Array holding the class names of other startup tasks on which the startup task depends.| Object array| Yes (initial value: left empty)|
125        | excludeFromAutoStart | Whether to exclude the automatic mode. For details, see [Changing the Startup Mode](#optional-changing-the-startup-mode).<br>- **true**: manual mode.<br>- **false**: automatic mode.| Boolean| Yes (initial value: **false**)|
126        | runOnThread | Thread where the startup task is executed.<br>- **mainThread**: executed in the main thread.<br>- **taskPool**: executed in an asynchronous thread.| String| Yes (initial value: **mainThread**)|
127        | waitOnMainThread | Whether the main thread needs to wait until the startup task finishes execution. This parameter is valid only when **runOnThread** is set to **taskPool**.<br>- **true**: The main thread loads the application home page only the startup task finishes execution.<br>- **false**: The main thread does not wait for the startup task to finish execution.| Boolean| Yes (initial value: **true**)|
128        
129    3. Add the index of the AppStartup configuration file to the **appStartup** tag in the [module.json5 file](../quick-start/module-configuration-file.md).
130    
131        The following is an example of the **module.json5** file:
132    
133          ```json
134              {
135                "module": {
136                  "name": "entry",
137                  "type": "entry",
138                  // ...
139                  "appStartup": "$profile:startup_config," // AppStartup configuration file
140                  // ...
141                }
142              }
143          ```
144
145### Setting Startup Parameters
146
147In the startup parameter file (**ets/startup/StartupConfig.ets** in this example), call [StartupConfigEntry](../reference/apis-ability-kit/js-apis-app-appstartup-startupConfigEntry.md) to set the common AppStartup parameters, including the timeout interval and listener.
148
149- [StartupConfig](../reference/apis-ability-kit/js-apis-app-appstartup-startupConfig.md): sets the task timeout interval and AppStartup listener.
150- [StartupListener](../reference/apis-ability-kit/js-apis-app-appstartup-startupListener.md): listens for the execution result of the startup task.
151
152```ts
153import { StartupConfig, StartupConfigEntry, StartupListener } from '@kit.AbilityKit';
154import { hilog } from '@kit.PerformanceAnalysisKit';
155import { BusinessError } from '@kit.BasicServicesKit';
156
157export default class MyStartupConfigEntry extends StartupConfigEntry {
158  onConfig() {
159    hilog.info(0x0000, 'testTag', `onConfig`);
160    let onCompletedCallback = (error: BusinessError<void>) => {
161      hilog.info(0x0000, 'testTag', `onCompletedCallback`);
162      if (error) {
163        hilog.info(0x0000, 'testTag', 'onCompletedCallback: %{public}d, message: %{public}s', error.code, error.message);
164      } else {
165        hilog.info(0x0000, 'testTag', `onCompletedCallback: success.`);
166      }
167    };
168    let startupListener: StartupListener = {
169      'onCompleted': onCompletedCallback
170    };
171    let config: StartupConfig = {
172      'timeoutMs': 10000,
173      'startupListener': startupListener
174    };
175    return config;
176  }
177}
178```
179
180### Adding a Startup Task for Each Component to Be Initialized
181
182Through the preceding operations, you have configured the AppStartup configuration file and startup parameters. Now you need to implement [StartupTask](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md) in each startup task file by calling the following two APIs:
183
184- [init](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md#startuptaskinit): starts task initialization. Call **init** to initialize a task only after all startup tasks on which the task depends are executed, that is, after **onDependencyCompleted** is invoked.
185- [onDependencyCompleted](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md#startuptaskondependencycompleted): invoked when the startup task on which the current task depends is complete.
186
187
188The following uses the **StartupTask_001.ets** file in [startup_config.json](#defining-an-appstartup-configuration-file) as an example. You must add a startup task for each component to be initialized.
189
190> **NOTE**
191> 
192> **StartupTask** follows the [Sendable](../arkts-utils/arkts-sendable.md) protocol. Therefore, the Sendable annotation must be added when this API is inherited.
193
194```ts
195import { StartupTask, common } from '@kit.AbilityKit';
196import { hilog } from '@kit.PerformanceAnalysisKit';
197
198@Sendable
199export default class StartupTask_001 extends StartupTask {
200  constructor() {
201    super();
202  }
203
204  async init(context: common.AbilityStageContext) {
205    hilog.info(0x0000, 'testTag', 'StartupTask_001 init.');
206    return 'StartupTask_001';
207  }
208
209  onDependencyCompleted(dependence: string, result: Object): void {
210    hilog.info(0x0000, 'testTag', 'StartupTask_001 onDependencyCompleted, dependence: %{public}s, result: %{public}s',
211      dependence, JSON.stringify(result));
212  }
213}
214```
215
216### (Optional) Changing the Startup Mode
217
218AppStartup provides automatic and manual mode. By default, the automatic mode is used. However, you can change the mode to manual as required.
219
220- Automatic mode: After an AbilityStage is created, the startup task is automatically executed.
221- Manual mode: After a UIAbility is created, you need to manually call the API to execute the startup task. Modules that are infrequently used do not need to be initialized when the application is started. You can change the startup mode of these modules to manual. After the application is started, you can call [startupManager.run](../reference/apis-ability-kit/js-apis-app-appstartup-startupManager.md#startupmanagerrun) to execute the startup task.
222
223The following uses the **onCreate** lifecycle of the UIAbility as an example to describe how to manually trigger a startup task. The sample code is as follows:
224
225```ts
226import { AbilityConstant, UIAbility, Want, startupManager } from '@kit.AbilityKit';
227import { hilog } from '@kit.PerformanceAnalysisKit';
228import { BusinessError } from '@kit.BasicServicesKit';
229
230export default class EntryAbility extends UIAbility {
231  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
232    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
233    let startParams = ['StartupTask_005', 'StartupTask_006'];
234    try {
235      startupManager.run(startParams).then(() => {
236        console.log('StartupTest startupManager run then, startParams = ');
237      }).catch((error: BusinessError) => {
238        console.info("StartupTest promise catch error, error = " + JSON.stringify(error));
239        console.info("StartupTest promise catch error, startParams = "
240          + JSON.stringify(startParams));
241      })
242    } catch (error) {
243      let errMsg = JSON.stringify(error);
244      let errCode: number = error.code;
245      console.log('Startup catch error , errCode= ' + errCode);
246      console.log('Startup catch error ,error= ' + errMsg);
247    }
248  }
249
250  // ...
251}
252```
253
254You can also call the API to trigger the manual mode after a page is loaded. The sample code is as follows:
255
256```ts
257import { startupManager } from '@kit.AbilityKit';
258
259@Entry
260@Component
261struct Index {
262  @State message: string = 'Manual Mode'
263  @State startParams: Array<string> = ['StartupTask_006'];
264
265  build() {
266    RelativeContainer() {
267      Button(this.message)
268        .id('AppStartup')
269        .fontSize(20)
270        .fontWeight(FontWeight.Bold)
271        .onClick(() => {
272          if (!startupManager.isStartupTaskInitialized("StartupTask_006")) { // Check whether the startup task finishes execution.
273            startupManager.run(this.startParams)
274          }
275        })
276        .alignRules({
277          center: {anchor: '__container__', align: VerticalAlign.Center},
278          middle: {anchor: '__container__', align: HorizontalAlign.Center}
279        })
280    }
281    .height('100%')
282    .width('100%')
283  }
284}
285```
286
287