• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Data Synchronization Between UIAbility and UI
2
3
4Based on the OpenHarmony application model, you can use any of the following ways to implement data synchronization between the UIAbility component and UI:
5
6- EventHub: The [base class Context](application-context-stage.md) provides the EventHub capability. It is implemented based on the publish/subscribe (pub/sub) pattern. Your application subscribes to an event and when the event occurs, receives a notification.
7
8- globalThis: It is a global object accessible in the ArkTS engine instance.
9- LocalStorage/AppStorage: See [State Management of Application-Level Variables](../quick-start/arkts-state-mgmt-application-level.md).
10
11
12## Using EventHub for Data Synchronization
13
14[EventHub](../reference/apis/js-apis-inner-application-eventHub.md) provides an event mechanism at the UIAbility or ExtensionAbility component level. Centered on the UIAbility or ExtensionAbility component, EventHub provides data communication capabilities for subscribing to, unsubscribing from, and triggering events.
15
16Before using EventHub, you must obtain an EventHub object, which is provided by the [base class Context](application-context-stage.md). This section uses EventHub as an example to describe how to implement data synchronization between the UIAbility component and the UI.
17
181. Call [eventHub.on()](../reference/apis/js-apis-inner-application-eventHub.md#eventhubon) in the UIAbility in either of the following ways to register a custom event **event1**.
19
20   ```ts
21   import UIAbility from '@ohos.app.ability.UIAbility';
22
23   const TAG: string = '[Example].[Entry].[EntryAbility]';
24
25   export default class EntryAbility extends UIAbility {
26       func1(...data) {
27           // Trigger the event to complete the service operation.
28           console.info(TAG, '1. ' + JSON.stringify(data));
29       }
30
31       onCreate(want, launch) {
32           // Obtain an eventHub object.
33           let eventhub = this.context.eventHub;
34           // Subscribe to the event.
35           eventhub.on('event1', this.func1);
36           eventhub.on('event1', (...data) => {
37               // Trigger the event to complete the service operation.
38               console.info(TAG, '2. ' + JSON.stringify(data));
39           });
40       }
41   }
42   ```
43
442. Call [eventHub.emit()](../reference/apis/js-apis-inner-application-eventHub.md#eventhubemit) on the UI to trigger the event, and pass the parameters as required.
45
46   ```ts
47   import common from '@ohos.app.ability.common';
48
49   @Entry
50   @Component
51   struct Index {
52     private context = getContext(this) as common.UIAbilityContext;
53
54     eventHubFunc() {
55       // Trigger the event without parameters.
56       this.context.eventHub.emit('event1');
57       // Trigger the event with one parameter.
58       this.context.eventHub.emit('event1', 1);
59       // Trigger the event with two parameters.
60       this.context.eventHub.emit('event1', 2, 'test');
61       // You can design the parameters based on your service requirements.
62     }
63
64     // Page display.
65     build() {
66       // ...
67     }
68   }
69   ```
70
713. Obtain the event trigger result from the subscription callback of UIAbility. The run log result is as follows:
72
73   ```ts
74   []
75
76   [1]
77
78   [2,'test']
79   ```
80
814. After **event1** is used, you can call [eventHub.off()](../reference/apis/js-apis-inner-application-eventHub.md#eventhuboff) to unsubscribe from the event.
82
83   ```ts
84   // context is the ability context of the UIAbility instance.
85   this.context.eventHub.off('event1');
86   ```
87
88
89## Using globalThis for Data Synchronization
90
91
92**globalThis** is a global object inside the [ArkTS engine instance](thread-model-stage.md) and can be used by UIAbility, ExtensionAbility, and Page inside the engine. Therefore, you can use **globalThis** for data synchronization.
93
94  **Figure 1** Using globalThis for data synchronization
95
96  ![globalThis1](figures/globalThis1.png)
97
98
99The following describes how to use **globalThis** in three scenarios. Precautions are provided as well.
100
101- [Using globalThis Between UIAbility and Page](#using-globalthis-between-uiability-and-page)
102- [Using globalThis Between UIAbility and UIAbility](##using-globalthis-between-uiability-and-uiability)
103- [Use globalThis Between UIAbility and ExtensionAbility](#using-globalthis-between-uiability-and-extensionability)
104- [Precautions for Using globalThis](#precautions-for-using-globalthis)
105
106### Using globalThis Between UIAbility and Page
107
108You can use **globalThis** to bind attributes or methods to implement data synchronization between the UIAbility component and UI. For example, if you bind the **want** parameter in the UIAbility component, you can use the **want** parameter information on the UI corresponding to the UIAbility component.
109
1101. When **startAbility()** is called to start a UIAbility instance, the **onCreate()** callback is invoked, and the **want** parameter can be passed in the callback. Therefore, you can bind the **want** parameter to **globalThis**.
111
112   ```ts
113   import UIAbility from '@ohos.app.ability.UIAbility'
114
115   export default class EntryAbility extends UIAbility {
116       onCreate(want, launch) {
117           globalThis.entryAbilityWant = want;
118           // ...
119       }
120
121       // ...
122   }
123   ```
124
1252. Use **globalThis** on the UI to obtain the **want** parameter information.
126
127   ```ts
128   let entryAbilityWant;
129
130   @Entry
131   @Component
132   struct Index {
133     aboutToAppear() {
134       entryAbilityWant = globalThis.entryAbilityWant;
135     }
136
137     // Page display.
138     build() {
139       // ...
140     }
141   }
142   ```
143
144
145### Using globalThis Between UIAbility and UIAbility
146
147To implement data synchronization between two UIAbility components in the same application, you can bind data to **globalThis**. For example, you can save data in **globalThis** in AbilityA and obtain the data from AbilityB.
148
1491. AbilityA stores a string and binds it to globalThis.
150
151   ```ts
152   import UIAbility from '@ohos.app.ability.UIAbility'
153
154   export default class AbilityA extends UIAbility {
155       onCreate(want, launch) {
156           globalThis.entryAbilityStr = 'AbilityA'; // AbilityA stores the string "AbilityA" to globalThis.
157           // ...
158       }
159   }
160   ```
161
1622. Obtain the data from AbilityB.
163
164   ```ts
165   import UIAbility from '@ohos.app.ability.UIAbility'
166
167   export default class AbilityB extends UIAbility {
168       onCreate(want, launch) {
169           // AbilityB reads the name from globalThis and outputs it.
170           console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
171           // ...
172       }
173   }
174   ```
175
176
177### Using globalThis Between UIAbility and ExtensionAbility
178
179To implement data synchronization between the UIAbility and ExtensionAbility components in the same application, you can bind data to **globalThis**. For example, you can save data in **globalThis** in AbilityA and obtain the data from ServiceExtensionAbility.
180
1811. AbilityA stores a string and binds it to globalThis.
182
183   ```ts
184   import UIAbility from '@ohos.app.ability.UIAbility'
185
186   export default class AbilityA extends UIAbility {
187       onCreate(want, launch) {
188           // AbilityA stores the string "AbilityA" to globalThis.
189           globalThis.entryAbilityStr = 'AbilityA';
190           // ...
191       }
192   }
193   ```
194
1952. Obtain the data from ExtensionAbility.
196
197   ```ts
198   import Extension from '@ohos.app.ability.ServiceExtensionAbility'
199
200   export default class ServiceExtAbility extends Extension {
201       onCreate(want) {
202           / / ServiceExtAbility reads name from globalThis and outputs it.
203           console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
204           // ...
205       }
206   }
207   ```
208
209
210### Precautions for Using globalThis
211
212  **Figure 2** Precautions for globalThis
213
214![globalThis2](figures/globalThis2.png)
215
216- In the stage model, all the UIAbility components in a process share one ArkTS engine instance. When using **globalThis**, do not store objects with the same name. For example, if AbilityA and AbilityB use **globalThis** to store two objects with the same name, the object stored earlier will be overwritten.
217
218- This problem does not occur in the FA model because each UIAbility component uses an independent engine.
219
220- The lifecycle of an object bound to **globalThis** is the same as that of the ArkTS engine instance. You are advised to assign the value **null** after using the object to minimize memory usage.
221
222The following provides an example to describe the object overwritten problem in the stage model.
223
2241. In the AbilityA file, [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) is stored in **globalThis**.
225
226   ```ts
227   import UIAbility from '@ohos.app.ability.UIAbility'
228
229   export default class AbilityA extends UIAbility {
230       onCreate(want, launch) {
231           globalThis.context = this.context; // AbilityA stores the context in globalThis.
232           // ...
233       }
234   }
235   ```
236
2372. Obtain and use [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) on the page of Ability A. After the AbilityA instance is used, switch it to the background.
238
239   ```ts
240   @Entry
241   @Component
242   struct Index {
243     onPageShow() {
244       let ctx = globalThis.context; // Obtain the context from globalThis and use it.
245       let permissions = ['com.example.permission']
246       ctx.requestPermissionsFromUser(permissions,(result) => {
247          // ...
248       });
249     }
250     // Page display.
251     build() {
252       // ...
253     }
254   }
255   ```
256
2573. In the AbilityB file, [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) is stored in **globalThis** and has the same name as that in the AbilityA file.
258
259   ```ts
260   import UIAbility from '@ohos.app.ability.UIAbility'
261
262   export default class AbilityB extends UIAbility {
263       onCreate(want, launch) {
264           // AbilityB overwrites the context stored by AbilityA in globalThis.
265           globalThis.context = this.context;
266           // ...
267       }
268   }
269   ```
270
2714. Obtain and use [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) on the page of Ability B. The obtained **globalThis.context** is the value of [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) in AbilityB.
272
273   ```ts
274   @Entry
275   @Component
276   struct Index {
277     onPageShow() {
278       let ctx = globalThis.context; // Obtain the context from globalThis and use it.
279       let permissions = ['com.example.permission']
280       ctx.requestPermissionsFromUser(permissions,(result) => {
281         console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
282       });
283     }
284     // Page display.
285     build() {
286       // ...
287     }
288   }
289   ```
290
2915. Switch the AbilityB instance to the background and switch the AbilityA instance to the foreground. In this case, AbilityA will not enter the **onCreate()** lifecycle again.
292
293   ```ts
294   import UIAbility from '@ohos.app.ability.UIAbility'
295
296   export default class AbilityA extends UIAbility {
297       onCreate(want, launch) { // AbilityA will not enter this lifecycle.
298           globalThis.context = this.context;
299           // ...
300       }
301   }
302   ```
303
3046. When the page of AbilityA is displayed, the obtained **globalThis.context** is [UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md) of AbilityB instead of AbilityA. An error occurs.
305
306   ```ts
307   @Entry
308   @Component
309   struct Index {
310     onPageShow() {
311       let ctx = globalThis.context; // The context in globalThis is the context of AbilityB.
312       let permissions=['com.example.permission'];
313       ctx.requestPermissionsFromUser(permissions,(result) => { // Using this object causes a process breakdown.
314          console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
315       });
316     }
317     // Page display.
318     build() {
319       // ...
320     }
321   }
322   ```
323