HarmonyOS/OpenHarmony application development - Stage model UIAbility component use (4)

Data synchronization between UIAbility components and UI
Based on the HarmonyOS application model, data synchronization between UIAbility components and UI can be realized in the following two ways.
1. EventHub: It is implemented based on the publish-subscribe model. Events need to be subscribed first and then published. Subscribers process the messages after receiving them.

2. globalThis: A global object inside the ArkTS engine instance, which can be accessed inside the ArkTS engine instance.

1. Using EventHub for data communication
EventHub provides a UIAbility component/ExtensionAbility component-level event mechanism, and provides data communication capabilities for subscribing, unsubscribing, and triggering events centered on the UIAbility component/ExtensionAbility component.
Before using EventHub, you first need to obtain the EventHub object. The base class Context provides the EventHub object. This chapter uses EventHub to implement data communication between UIAbility and UI as an example.

1. Call the eventHub.on() method in UIAbility to register a custom event "event1". eventHub.on() has the following two calling methods, use one of them.

import UIAbility from '@ohos.app.ability.UIAbility';

const TAG: string = '[Example].[Entry].[EntryAbility]';

export default class EntryAbility extends UIAbility {
    func1(...data) {
        // 触发事件,完成相应的业务操作
        console.info(TAG, '1. ' + JSON.stringify(data));
    }

    onCreate(want, launch) {
        // 获取eventHub
        let eventhub = this.context.eventHub;
        // 执行订阅操作
        eventhub.on('event1', this.func1);
        eventhub.on('event1', (...data) => {
            // 触发事件,完成相应的业务操作
            console.info(TAG, '2. ' + JSON.stringify(data));
        });
    }
}

2. Trigger the event through the eventHub.emit() method in the UI interface, and pass in parameter information as needed while triggering the event.

3. The corresponding trigger event result can be obtained in the registration event callback of UIAbility, and the operation log result is as follows.

[]

[1]

[2,'test']

4. After using the custom event "event1", you can call the eventHub.off() method to cancel the subscription of the event as needed.

// context为UIAbility实例的AbilityContext
this.context.eventHub.off('event1');

2. Use globalThis for data synchronization
globalThis is a global object inside the ArkTS engine instance, and UIAbility/ExtensionAbility/Page inside the engine can be used, so you can use the globalThis global object for data synchronization.
Figure 1 Using globalThis for data synchronization


As shown in the figure above, the use of globalThis is introduced from the following three scenarios and a point of attention:
Use globalThis between UIAbility and Page Use globalThis
between UIAbility and UIAbility Use globalThis between
UIAbility and ExtensionAbility Use globalThis
Precautions for using globalThis
Three, UIAbility Use globalThis with Page.
globalThis is the global object under the ArkTS engine instance, and you can use globalThis to bind properties/methods to synchronize UIAbility components and UI data. For example, if you bind the want parameter in the UIAbility component, you can use the want parameter information on the UI interface corresponding to the UIAbility.
1. When the startAbility() method is called to start a UIAbility instance, the started UIAbility will enter the onCreate() life cycle callback after the creation is completed, and the want parameter passed in the onCreate() life cycle callback can be received, and the want can be set Parameters are bound to globalThis.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class EntryAbility extends UIAbility {
    onCreate(want, launch) {
        globalThis.entryAbilityWant = want;
        // ...
    }

    // ...
}

2. In the UI interface, you can get the want parameter information through globalThis.

let entryAbilityWant;

@Entry
@Component
struct Index {
  aboutToAppear() {
    entryAbilityWant = globalThis.entryAbilityWant;
  }

  // 页面展示
  build() {
    // ...
  }
}

3. Use globalThis between UIAbility and UIAbility
The data transfer between UIAbility and UIAbility in the same application can be synchronized by binding the data to the global variable globalThis, such as saving the data in globalThis in AbilityA, and then jumping to Obtain the data in AbilityB:
1. Save the data in AbilityA as a string data and mount it on globalThis.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class AbilityA extends UIAbility {
    onCreate(want, launch) {
        globalThis.entryAbilityStr = 'AbilityA'; // AbilityA存放字符串“AbilityA”到globalThis
        // ...
    }
}

2. Obtain the corresponding data in AbilityB.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class AbilityB extends UIAbility {
    onCreate(want, launch) {
        // AbilityB从globalThis读取name并输出
        console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
        // ...
    }
}

4. Use globalThis between UIAbility and ExtensionAbility
The data transfer between UIAbility and ExtensionAbility in the same application can also be synchronized by binding the data to the global variable globalThis, such as saving data in AbilityA and obtaining data in ServiceExtensionAbility.
1. Save a string of data in AbilityA and mount it to globalThis.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class AbilityA extends UIAbility {
    onCreate(want, launch) {
        // AbilityA存放字符串“AbilityA”到globalThis
        globalThis.entryAbilityStr = 'AbilityA';
        // ...
    }
}

2. Get data in ExtensionAbility.

import Extension from '@ohos.app.ability.ServiceExtensionAbility'

export default class ServiceExtAbility extends Extension {
    onCreate(want) {
        // ServiceExtAbility从globalThis读取name并输出
        console.info('name from entryAbilityStr: ' + globalThis.entryAbilityStr);
        // ...
    

5. Precautions for using globalThis
Figure 2 Precautions for globalThis


The in-process UIAbility components under the Stage model share the ArkTS engine instance. When using globalThis, it is necessary to avoid storing objects with the same name. For example, AbilityA and AbilityB can use globalThis to share data. When storing objects with the same name, the object stored first will be overwritten by the object stored later.
The FA model does not have this problem because of the engine isolation between each UIAbility component.
For the object bound to globalThis, its life cycle is the same as that of the ArkTS virtual machine instance. It is recommended to assign it to null after use to reduce the memory usage of the application.
An example of a scene where an object with the same name on the Stage model causes a problem is illustrated.

1. Use globalThis to store UIAbilityContext in the AbilityA file.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class AbilityA extends UIAbility {
    onCreate(want, launch) {
        globalThis.context = this.context; // AbilityA存放context到globalThis
        // ...
    }
}

2. Obtain the UIAbilityContext in the page of AbilityA and use it. Switch the AbilityA instance to the background after use.

@Entry
@Component
struct Index {
  onPageShow() {
    let ctx = globalThis.context; // 页面中从globalThis中取出context并使用
    let permissions = ['com.example.permission']
    ctx.requestPermissionsFromUser(permissions,(result) => {
       // ...
    });
  }
  // 页面展示
  build() {
    // ...
  }
}

3. In the AbilityB file, use globalThis to store the UIAbilityContext and name it the same name.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class AbilityB extends UIAbility {
    onCreate(want, launch) {
        // AbilityB覆盖了AbilityA在globalThis中存放的context
        globalThis.context = this.context;
        // ...
    }
}

4. Obtain the UIAbilityContext in the page of AbilityB and use it. The globalThis.context obtained at this time has been represented as the UIAbilityContext content assigned in AbilityB.

undefined@Entry
@Component
struct Index {
  onPageShow() {
    let ctx = globalThis.context; // Page中从globalThis中取出context并使用
    let permissions = ['com.example.permission']
    ctx.requestPermissionsFromUser(permissions,(result) => {
      console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
    });
  }
  // 页面展示
  build() {
    // ...
  }
}

5. After the AbilityB instance switches to the background, switch the AbilityA instance from the background back to the foreground. At this time, the onCreate life cycle of AbilityA will not enter again.

import UIAbility from '@ohos.app.ability.UIAbility'

export default class AbilityA extends UIAbility {
    onCreate(want, launch) { // AbilityA从后台进入前台,不会再走这个生命周期
        globalThis.context = this.context;
        // ...
    }
}

6. When the page of AbilityA returns to the foreground again, the globalThis.context obtained by it represents the UIAbilityContext of AbilityB, not the UIAbilityContext of AbilityA. If it is used in the page of AbilityA, an error will occur.

@Entry
@Component
struct Index {
  onPageShow() {
    let ctx = globalThis.context; // 这时候globalThis中的context是AbilityB的context
    let permissions=['com.example.permission'];
    ctx.requestPermissionsFromUser(permissions,(result) => { // 使用这个对象就会导致进程崩溃
       console.info('requestPermissionsFromUser result:' + JSON.stringify(result));
    });
  }
  // 页面展示
  build() {
    // ...
  }
}

Guess you like

Origin blog.csdn.net/weixin_69135651/article/details/131702909