UIAbility組件與UI的數(shù)據(jù)同步

2024-01-25 12:15 更新

基于HarmonyOS的應(yīng)用模型,可以通過以下兩種方式來實(shí)現(xiàn)UIAbility組件與UI之間的數(shù)據(jù)同步。

使用EventHub進(jìn)行數(shù)據(jù)通信

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

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

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

    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īng)的業(yè)務(wù)操作
    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īng)的業(yè)務(wù)操作
    15. console.info(TAG, '2. ' + JSON.stringify(data));
    16. });
    17. }
    18. }
  2. 在UI界面中通過eventHub.emit()方法觸發(fā)該事件,在觸發(fā)事件的同時(shí),根據(jù)需要傳入?yún)?shù)信息。

    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. // 不帶參數(shù)觸發(fā)自定義“event1”事件
    8. this.context.eventHub.emit('event1');
    9. // 帶1個(gè)參數(shù)觸發(fā)自定義“event1”事件
    10. this.context.eventHub.emit('event1', 1);
    11. // 帶2個(gè)參數(shù)觸發(fā)自定義“event1”事件
    12. this.context.eventHub.emit('event1', 2, 'test');
    13. // 開發(fā)者可以根據(jù)實(shí)際的業(yè)務(wù)場景設(shè)計(jì)事件傳遞的參數(shù)
    14. }
    15. // 頁面展示
    16. build() {
    17. // ...
    18. }
    19. }
  3. 在UIAbility的注冊事件回調(diào)中可以得到對應(yīng)的觸發(fā)事件結(jié)果,運(yùn)行日志結(jié)果如下所示。

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

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

使用globalThis進(jìn)行數(shù)據(jù)同步

globalThis是ArkTS引擎實(shí)例內(nèi)部的一個(gè)全局對象,引擎內(nèi)部的UIAbility/ExtensionAbility/Page都可以使用,因此可以使用globalThis全局對象進(jìn)行數(shù)據(jù)同步。

圖1 使用globalThis進(jìn)行數(shù)據(jù)同步

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

UIAbility和Page之間使用globalThis

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

  1. 調(diào)用startAbility()方法啟動一個(gè)UIAbility實(shí)例時(shí),被啟動的UIAbility創(chuàng)建完成后會進(jìn)入onCreate()生命周期回調(diào),且在onCreate()生命周期回調(diào)中能夠接受到傳遞過來的want參數(shù),可以將want參數(shù)綁定到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參數(shù)信息。

    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

同一個(gè)應(yīng)用中UIAbility和UIAbility之間的數(shù)據(jù)傳遞,可以通過將數(shù)據(jù)綁定到全局變量globalThis上進(jìn)行同步,如在AbilityA中將數(shù)據(jù)保存在globalThis,然后跳轉(zhuǎn)到AbilityB中取得該數(shù)據(jù):

  1. AbilityA中保存數(shù)據(jù)一個(gè)字符串?dāng)?shù)據(jù)并掛載到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中獲取對應(yīng)的數(shù)據(jù)。

    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使用的注意事項(xiàng)

圖2 globalThis注意事項(xiàng)

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

  • FA模型因?yàn)槊總€(gè)UIAbility組件之間引擎隔離,不會存在該問題。

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

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

  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并進(jìn)行使用。使用完成后將AbilityA實(shí)例切換至后臺。

    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并進(jìn)行使用。此時(shí)獲取到的globalThis.context已經(jīng)表示為AbilityB中賦值的UIAbilityContext內(nèi)容。

    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實(shí)例切換至后臺,將AbilityA實(shí)例從后臺切換回到前臺。此時(shí)AbilityA的onCreate生命周期不會再次進(jìn)入。

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

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

使用AppStorage/LocalStorage進(jìn)行數(shù)據(jù)同步

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

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號