UIAbility組件與UI的數據同步

2024-01-25 12:15 更新

基于HarmonyOS的應用模型,可以通過以下兩種方式來實現UIAbility組件與UI之間的數據同步。

使用EventHub進行數據通信

EventHub提供了UIAbility組件/ExtensionAbility組件級別的事件機制,以UIAbility組件/ExtensionAbility組件為中心提供了訂閱、取消訂閱和觸發(fā)事件的數據通信能力。接口說明請參見EventHub。

在使用EventHub之前,首先需要獲取EventHub對象。基類Context提供了EventHub對象,本章節(jié)以使用EventHub實現UIAbility與UI之間的數據通信為例進行說明。

  1. 在UIAbility中調用eventHub.on()方法注冊一個自定義事件“event1”,eventHub.on()有如下兩種調用方式,使用其中一種即可。

    1. import UIAbility from '@ohos.app.ability.UIAbility';
    2. const TAG: string = '[Example].[Entry].[EntryAbility]';
    3. export default class EntryAbility extends UIAbility {
    4. func1(...data) {
    5. // 觸發(fā)事件,完成相應的業(yè)務操作
    6. console.info(TAG, '1. ' + JSON.stringify(data));
    7. }
    8. onCreate(want, launch) {
    9. // 獲取eventHub
    10. let eventhub = this.context.eventHub;
    11. // 執(zhí)行訂閱操作
    12. eventhub.on('event1', this.func1);
    13. eventhub.on('event1', (...data) => {
    14. // 觸發(fā)事件,完成相應的業(yè)務操作
    15. console.info(TAG, '2. ' + JSON.stringify(data));
    16. });
    17. }
    18. }
  2. 在UI界面中通過eventHub.emit()方法觸發(fā)該事件,在觸發(fā)事件的同時,根據需要傳入參數信息。

    1. import common from '@ohos.app.ability.common';
    2. @Entry
    3. @Component
    4. struct Index {
    5. private context = getContext(this) as common.UIAbilityContext;
    6. eventHubFunc() {
    7. // 不帶參數觸發(fā)自定義“event1”事件
    8. this.context.eventHub.emit('event1');
    9. // 帶1個參數觸發(fā)自定義“event1”事件
    10. this.context.eventHub.emit('event1', 1);
    11. // 帶2個參數觸發(fā)自定義“event1”事件
    12. this.context.eventHub.emit('event1', 2, 'test');
    13. // 開發(fā)者可以根據實際的業(yè)務場景設計事件傳遞的參數
    14. }
    15. // 頁面展示
    16. build() {
    17. // ...
    18. }
    19. }
  3. 在UIAbility的注冊事件回調中可以得到對應的觸發(fā)事件結果,運行日志結果如下所示。

    1. []
    2. [1]
    3. [2,'test']
  4. 在自定義事件“event1”使用完成后,可以根據需要調用eventHub.off()方法取消該事件的訂閱。

    1. // context為UIAbility實例的AbilityContext
    2. this.context.eventHub.off('event1');

使用globalThis進行數據同步

globalThis是ArkTS引擎實例內部的一個全局對象,引擎內部的UIAbility/ExtensionAbility/Page都可以使用,因此可以使用globalThis全局對象進行數據同步。

圖1 使用globalThis進行數據同步

如上圖所示,下面來具體介紹globalThis的使用:

UIAbility和Page之間使用globalThis

globalThis為ArkTS引擎實例下的全局對象,可以通過globalThis綁定屬性/方法來進行UIAbility組件與UI的數據同步。例如在UIAbility組件中綁定want參數,即可在UIAbility對應的UI界面上使用want參數信息。

  1. 調用startAbility()方法啟動一個UIAbility實例時,被啟動的UIAbility創(chuàng)建完成后會進入onCreate()生命周期回調,且在onCreate()生命周期回調中能夠接受到傳遞過來的want參數,可以將want參數綁定到globalThis上。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class EntryAbility extends UIAbility {
    3. onCreate(want, launch) {
    4. globalThis.entryAbilityWant = want;
    5. // ...
    6. }
    7. // ...
    8. }
  2. 在UI界面中即可通過globalThis獲取到want參數信息。

    1. let entryAbilityWant;
    2. @Entry
    3. @Component
    4. struct Index {
    5. aboutToAppear() {
    6. entryAbilityWant = globalThis.entryAbilityWant;
    7. }
    8. // 頁面展示
    9. build() {
    10. // ...
    11. }
    12. }

UIAbility和UIAbility之間使用globalThis

同一個應用中UIAbility和UIAbility之間的數據傳遞,可以通過將數據綁定到全局變量globalThis上進行同步,如在AbilityA中將數據保存在globalThis,然后跳轉到AbilityB中取得該數據:

  1. AbilityA中保存數據一個字符串數據并掛載到globalThis上。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class AbilityA extends UIAbility {
    3. onCreate(want, launch) {
    4. globalThis.entryAbilityStr = 'AbilityA'; // AbilityA存放字符串“AbilityA”到globalThis
    5. // ...
    6. }
    7. }
  2. AbilityB中獲取對應的數據。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class AbilityB extends UIAbility {
    3. onCreate(want, launch) {
    4. // AbilityB從globalThis讀取name并輸出
    5. console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
    6. // ...
    7. }
    8. }

globalThis使用的注意事項

圖2 globalThis注意事項

  • Stage模型下進程內的UIAbility組件共享ArkTS引擎實例,使用globalThis時需要避免存放相同名稱的對象。例如AbilityA和AbilityB可以使用globalThis共享數據,在存放相同名稱的對象時,先存放的對象會被后存放的對象覆蓋。

  • FA模型因為每個UIAbility組件之間引擎隔離,不會存在該問題。

  • 對于綁定在globalThis上的對象,其生命周期與ArkTS虛擬機實例相同,建議在使用完成之后將其賦值為null,以減少對應用內存的占用。

Stage模型上同名對象覆蓋導致問題的場景舉例說明。

  1. 在AbilityA文件中使用globalThis存放了UIAbilityContext。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class AbilityA extends UIAbility {
    3. onCreate(want, launch) {
    4. globalThis.context = this.context; // AbilityA存放context到globalThis
    5. // ...
    6. }
    7. }
  2. 在AbilityA的頁面中獲取該UIAbilityContext并進行使用。使用完成后將AbilityA實例切換至后臺。

    1. @Entry
    2. @Component
    3. struct Index {
    4. onPageShow() {
    5. let ctx = globalThis.context; // 頁面中從globalThis中取出context并使用
    6. let permissions = ['com.example.permission']
    7. ctx.requestPermissionsFromUser(permissions,(result) => {
    8. // ...
    9. });
    10. }
    11. // 頁面展示
    12. build() {
    13. // ...
    14. }
    15. }
  3. 在AbilityB文件中使用globalThis存放了UIAbilityContext,并且命名為相同的名稱。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class AbilityB extends UIAbility {
    3. onCreate(want, launch) {
    4. // AbilityB覆蓋了AbilityA在globalThis中存放的context
    5. globalThis.context = this.context;
    6. // ...
    7. }
    8. }
  4. 在AbilityB的頁面中獲取該UIAbilityContext并進行使用。此時獲取到的globalThis.context已經表示為AbilityB中賦值的UIAbilityContext內容。

    1. @Entry
    2. @Component
    3. struct Index {
    4. onPageShow() {
    5. let ctx = globalThis.context; // Page中從globalThis中取出context并使用
    6. let permissions = ['com.example.permission']
    7. ctx.requestPermissionsFromUser(permissions,(result) => {
    8. console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
    9. });
    10. }
    11. // 頁面展示
    12. build() {
    13. // ...
    14. }
    15. }
  5. 在AbilityB實例切換至后臺,將AbilityA實例從后臺切換回到前臺。此時AbilityA的onCreate生命周期不會再次進入。

    1. import UIAbility from '@ohos.app.ability.UIAbility'
    2. export default class AbilityA extends UIAbility {
    3. onCreate(want, launch) { // AbilityA從后臺進入前臺,不會再走這個生命周期
    4. globalThis.context = this.context;
    5. // ...
    6. }
    7. }
  6. 在AbilityA的頁面再次回到前臺時,其獲取到的globalThis.context表示的為AbilityB的UIAbilityContext,而不是AbilityA的UIAbilityContext,在AbilityA的頁面中使用則會出錯。

    1. @Entry
    2. @Component
    3. struct Index {
    4. onPageShow() {
    5. let ctx = globalThis.context; // 這時候globalThis中的context是AbilityB的context
    6. let permissions=['com.example.permission'];
    7. ctx.requestPermissionsFromUser(permissions,(result) => { // 使用這個對象就會導致進程崩潰
    8. console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
    9. });
    10. }
    11. // 頁面展示
    12. build() {
    13. // ...
    14. }
    15. }

使用AppStorage/LocalStorage進行數據同步

ArkUI提供了AppStorage和LocalStorage兩種應用級別的狀態(tài)管理方案,可用于實現應用級別和UIAbility級別的數據同步。使用這些方案可以方便地管理應用狀態(tài),提高應用性能和用戶體驗。其中,AppStorage是一個全局的狀態(tài)管理器,適用于多個UIAbility共享同一狀態(tài)數據的情況;而LocalStorage則是一個局部的狀態(tài)管理器,適用于單個UIAbility內部使用的狀態(tài)數據。通過這兩種方案,開發(fā)者可以更加靈活地控制應用狀態(tài),提高應用的可維護性和可擴展性。詳細請參見應用級變量的狀態(tài)管理。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號