1# UIAbility组件与UI的数据同步 2 3 4基于OpenHarmony的应用模型,可以通过以下两种方式来实现UIAbility组件与UI之间的数据同步。 5 6 71. EventHub:基于发布订阅模式来实现,事件需要先订阅后发布,订阅者收到消息后进行处理。 8 92. globalThis:ArkTS引擎实例内部的一个全局对象,在ArkTS引擎实例内部都能访问。 10 11 12## 使用EventHub进行数据通信 13 14EventHub提供了UIAbility组件/ExtensionAbility组件级别的事件机制,以UIAbility组件/ExtensionAbility组件为中心提供了订阅、取消订阅和触发事件的数据通信能力。接口说明请参见[EventHub](../reference/apis/js-apis-inner-application-eventHub.md)。 15 16在使用EventHub之前,首先需要获取EventHub对象。[基类Context](application-context-stage.md)提供了EventHub对象,本章节以使用EventHub实现UIAbility与UI之间的数据通信为例进行说明。 17 181. 在UIAbility中调用eventHub.on()方法注册一个自定义事件“event1”,eventHub.on()有如下两种调用方式,使用其中一种即可。 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 // 触发事件,完成相应的业务操作 28 console.info(TAG, '1. ' + JSON.stringify(data)); 29 } 30 31 onCreate(want, launch) { 32 // 获取eventHub 33 let eventhub = this.context.eventHub; 34 // 执行订阅操作 35 eventhub.on('event1', this.func1); 36 eventhub.on('event1', (...data) => { 37 // 触发事件,完成相应的业务操作 38 console.info(TAG, '2. ' + JSON.stringify(data)); 39 }); 40 } 41 } 42 ``` 43 442. 在UI界面中通过eventHub.emit()方法触发该事件,在触发事件的同时,根据需要传入参数信息。 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 // 不带参数触发自定义“event1”事件 56 this.context.eventHub.emit('event1'); 57 // 带1个参数触发自定义“event1”事件 58 this.context.eventHub.emit('event1', 1); 59 // 带2个参数触发自定义“event1”事件 60 this.context.eventHub.emit('event1', 2, 'test'); 61 // 开发者可以根据实际的业务场景设计事件传递的参数 62 } 63 64 // 页面展示 65 build() { 66 // ... 67 } 68 } 69 ``` 70 713. 在UIAbility的注册事件回调中可以得到对应的触发事件结果,运行日志结果如下所示。 72 73 ```ts 74 [] 75 76 [1] 77 78 [2,'test'] 79 ``` 80 814. 在自定义事件“event1”使用完成后,可以根据需要调用eventHub.off()方法取消该事件的订阅。 82 83 ```ts 84 // context为UIAbility实例的AbilityContext 85 this.context.eventHub.off('event1'); 86 ``` 87 88 89## 使用globalThis进行数据同步 90 91 92globalThis是ArkTS引擎实例内部的一个全局对象,引擎内部的UIAbility/ExtensionAbility/Page都可以使用,因此可以使用globalThis全局对象进行数据同步。 93 94 **图1** 使用globalThis进行数据同步 95 96  97 98 99如上图所示,下面从如下三个场景和一个注意点来介绍globalThis的使用: 100 101- [UIAbility和Page之间使用globalThis](#uiability和page之间使用globalthis) 102- [UIAbility和UIAbility之间使用globalThis](#uiability和uiability之间使用globalthis) 103- [UIAbility和ExtensionAbility之间使用globalThis](#uiability和extensionability之间使用globalthis) 104- [globalThis使用的注意事项](#globalthis使用的注意事项) 105 106### UIAbility和Page之间使用globalThis 107 108globalThis为[ArkTS引擎实例](thread-model-stage.md)下的全局对象,可以通过globalThis绑定属性/方法来进行UIAbility组件与UI的数据同步。例如在UIAbility组件中绑定want参数,即可在UIAbility对应的UI界面上使用want参数信息。 109 1101. 调用startAbility()方法启动一个UIAbility实例时,被启动的UIAbility创建完成后会进入onCreate()生命周期回调,且在onCreate()生命周期回调中能够接受到传递过来的want参数,可以将want参数绑定到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. 在UI界面中即可通过globalThis获取到want参数信息。 126 127 ```ts 128 let entryAbilityWant; 129 130 @Entry 131 @Component 132 struct Index { 133 aboutToAppear() { 134 entryAbilityWant = globalThis.entryAbilityWant; 135 } 136 137 // 页面展示 138 build() { 139 // ... 140 } 141 } 142 ``` 143 144 145### UIAbility和UIAbility之间使用globalThis 146 147同一个应用中UIAbility和UIAbility之间的数据传递,可以通过将数据绑定到全局变量globalThis上进行同步,如在AbilityA中将数据保存在globalThis,然后跳转到AbilityB中取得该数据: 148 1491. AbilityA中保存数据一个字符串数据并挂载到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存放字符串“AbilityA”到globalThis 157 // ... 158 } 159 } 160 ``` 161 1622. 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从globalThis读取name并输出 170 console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr); 171 // ... 172 } 173 } 174 ``` 175 176 177### UIAbility和ExtensionAbility之间使用globalThis 178 179同一个应用中UIAbility和ExtensionAbility之间的数据传递,也可以通过将数据绑定到全局变量globalThis上进行同步,如在AbilityA中保存数据,在ServiceExtensionAbility中获取数据。 180 1811. AbilityA中保存数据一个字符串数据并挂载到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存放字符串“AbilityA”到globalThis 189 globalThis.entryAbilityStr = 'AbilityA'; 190 // ... 191 } 192 } 193 ``` 194 1952. 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从globalThis读取name并输出 203 console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr); 204 // ... 205 } 206 } 207 ``` 208 209 210### globalThis使用的注意事项 211 212 **图2** globalThis注意事项 213 214 215 216- Stage模型下进程内的UIAbility组件共享ArkTS引擎实例,使用globalThis时需要避免存放相同名称的对象。例如AbilityA和AbilityB可以使用globalThis共享数据,在存放相同名称的对象时,先存放的对象会被后存放的对象覆盖。 217 218- FA模型因为每个UIAbility组件之间引擎隔离,不会存在该问题。 219 220- 对于绑定在globalThis上的对象,其生命周期与ArkTS虚拟机实例相同,建议在使用完成之后将其赋值为null,以减少对应用内存的占用。 221 222Stage模型上同名对象覆盖导致问题的场景举例说明。 223 2241. 在AbilityA文件中使用globalThis中存放了[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md)。 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存放context到globalThis 232 // ... 233 } 234 } 235 ``` 236 2372. 在AbilityA的页面中获取该[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md)并进行使用。使用完成后将AbilityA实例切换至后台。 238 239 ```ts 240 @Entry 241 @Component 242 struct Index { 243 onPageShow() { 244 let ctx = globalThis.context; // 页面中从globalThis中取出context并使用 245 let permissions = ['com.example.permission'] 246 ctx.requestPermissionsFromUser(permissions,(result) => { 247 // ... 248 }); 249 } 250 // 页面展示 251 build() { 252 // ... 253 } 254 } 255 ``` 256 2573. 在AbilityB文件中使用globalThis中存放了[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md),并且命名为相同的名称。 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覆盖了AbilityA在globalThis中存放的context 265 globalThis.context = this.context; 266 // ... 267 } 268 } 269 ``` 270 2714. 在AbilityB的页面中获取该[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md)并进行使用。此时获取到的globalThis.context已经表示为AbilityB中赋值的[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md)内容。 272 273 ```ts 274 @Entry 275 @Component 276 struct Index { 277 onPageShow() { 278 let ctx = globalThis.context; // Page中从globalThis中取出context并使用 279 let permissions = ['com.example.permission'] 280 ctx.requestPermissionsFromUser(permissions,(result) => { 281 console.info('requestPermissionsFromUser result:' + JSON.stringify(result)); 282 }); 283 } 284 // 页面展示 285 build() { 286 // ... 287 } 288 } 289 ``` 290 2915. 在AbilityB实例切换至后台,将AbilityA实例从后台切换回到前台。此时AbilityA的onCreate生命周期不会再次进入。 292 293 ```ts 294 import UIAbility from '@ohos.app.ability.UIAbility' 295 296 export default class AbilityA extends UIAbility { 297 onCreate(want, launch) { // AbilityA从后台进入前台,不会再走这个生命周期 298 globalThis.context = this.context; 299 // ... 300 } 301 } 302 ``` 303 3046. 在AbilityA的页面再次回到前台时,其获取到的globalThis.context表示的为AbilityB的[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md),而不是AbilityA的[UIAbilityContext](../reference/apis/js-apis-inner-application-uiAbilityContext.md),在AbilityA的页面中使用则会出错。 305 306 ```ts 307 @Entry 308 @Component 309 struct Index { 310 onPageShow() { 311 let ctx = globalThis.context; // 这时候globalThis中的context是AbilityB的context 312 let permissions=['com.example.permission']; 313 ctx.requestPermissionsFromUser(permissions,(result) => { // 使用这个对象就会导致进程崩溃 314 console.info('requestPermissionsFromUser result:' + JSON.stringify(result)); 315 }); 316 } 317 // 页面展示 318 build() { 319 // ... 320 } 321 } 322 ``` 323