Page Ability

Page Ability

Page with AbilitySlice

The Page template (hereinafter referred to as “Page”) is the only template supported by FA to provide the ability to interact with users. A Page can be composed of one or more AbilitySlice, AbilitySlice refers to the application of a single Page and its control logic.

When a Page is composed of multiple AbilitySlice, the business capabilities provided by these AbilitySlice pages should be highly relevant. For example, the news browsing function can be implemented through a Page, which contains two AbilitySlice: one for displaying news list, the other for displaying news details. The relationship between Page and AbilitySlice is shown in Figure 1. Figure 1 Page with AbilitySlice

Compared with desktop scenarios, applications interact more frequently in mobile scenarios. Typically, a single application focuses on one aspect of capability development and calls capabilities provided by other applications when it needs assistance from other capabilities. For example, the food delivery app provides access to business functions. When users use this function, they will be redirected to the dial page of the calling app. Similarly, HarmonyOS supports jumping between different pages and can specify a specific AbilitySlice in the target Page.

AbilitySlice Route configuration

Although a Page can contain multiple AbilitySlice, but Page into the foreground interface default display only a AbilitySlice. The default displayed AbilitySlice is specified by the setMainRoute() method. If you need to change the default displayed AbilitySlice, configure a routing rule for this AbilitySlice using the addActionRoute() method. At this point, when other Page instances expect to navigate to the AbilitySlice, you can specify the Action in the Intent. See Navigation between pages.

Examples of setMainRoute() and addActionRoute() methods:

public class MyAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        // set the main route
        setMainRoute(MainSlice.class.getName());

        // set the action route
        addActionRoute("action.pay", PaySlice.class.getName());
        addActionRoute("action.scan", ScanSlice.class.getName()); }}Copy the code

The action names used in the addActionRoute() method need to be registered in the application configuration file (config.json) :

{
    "module": {
        "abilities": [{"skills":[
                    {
                        "actions": ["action.pay"."action.scan"]}]... }]... }... }Copy the code

Page Ability Lifecycle

Actions such as system administration or user actions can cause Page instances to transition between different states in their life cycle. The Callback mechanism provided by the Ability class allows The Page to be aware of changes in the external environment in time so that it can respond correctly to state changes (such as releasing resources), which can help improve the performance and robustness of an application.

Page lifecycle callback

The different state transitions of the Page lifecycle and their corresponding callbacks are shown in Figure 1. Figure 1 Page lifecycle

  • onStart()

This callback is triggered when the system first creates a Page instance. For a Page instance, the callback is triggered only once during its life cycle, and the Page enters an INACTIVE state after this logic. The developer must override this method and configure AbilitySlice to be displayed by default.

 @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(FooSlice.class.getName());
    }
Copy the code
  • onActive()

The Page comes to the foreground after it enters INACTIVE state, and the system calls this callback. The Page then enters the ACTIVE state, which is the state in which the application interacts with the user. The Page will remain in this state unless some kind of event occurs that causes the Page to lose focus, such as the user hitting the back key or navigating to another Page. When such an event occurs, the Page is triggered to return to INACTIVE, and the onInactive() callback is called. After that, the Page may return to the ACTIVE state, and the onActive() callback will be called again. Therefore, developers typically need to implement onActive() and onInactive() in pairs, and in onActive() acquire the resources freed in onInactive().

  • onInactive()

The system calls this callback when the Page loses focus, after which the Page enters INACTIVE state. In this callback, the developer can implement the appropriate behavior if the Page loses focus.

  • onBackground()

If the Page is no longer visible to the user, the system calls this callback to notify the developer that the user has made the appropriate resource release, after which the Page enters the BACKGROUND state. Developers should either release resources in this callback that are not available when the Page is not visible, or perform time-consuming state saving operations in this callback.

  • onForeground()

The Page in the BACKGROUND state still resides in memory. When it returns to the foreground (for example, when the user navigates to the Page again), the system first notifys the developer by invoking the onForeground() callback, and then the life cycle state of the Page returns to INACTIVE. The developer should rerequest the resources released in onBackground() in this callback, and finally the life cycle state of the Page will be further returned to the ACTIVE state, and the developer user will be notified via the onActive() callback.

  • onStop()
    • When the system is about to destroy the Page, this callback function is triggered to notify the user of the release of system resources. Possible reasons for Page destruction include the following:
    • The user closes the specified Page using the system management capability, such as using the task manager.
    • The user behavior triggers a call to the terminateAbility() method of Page, such as using an application’s exit function. The configuration change causes the system to temporarily destroy the Page and rebuild it.
    • The system automatically triggers the destruction of BACKGROUND pages for resource management purposes.
AbilitySlice Life cycle

AbilitySlice as a component of Page, its life cycle is dependent on its Page life cycle. AbilitySlice and Page have the same lifecycle status and callbacks of the same name. When the Page lifecycle changes, its AbilitySlice also has the same lifecycle change. In addition, AbilitySlice also has a Page independent lifecycle change, which occurs when navigating between AbilitySlice in the same Page, at which point the lifecycle state of the Page does not change.

The AbilitySlice lifecycle callback is similar to the corresponding callback for Page and is therefore not covered here. Since AbilitySlice hosts specific pages, the developer must override AbilitySlice’s onStart() callback and set up the page in this method via the setUIContent() method, as shown below:

@Override
protected void onStart(Intent intent) {
    super.onStart(intent);

    setUIContent(ResourceTable.Layout_main_layout);
}
Copy the code

AbilitySlice instance creation and management is usually the responsibility of the application, the system will only create AbilitySlice instances in specific circumstances. For example, when a AbilitySlice is navigated, it is the system’s responsibility to instantiate it; However, when navigating between AbilitySlice on the same Page, it is up to the application to instantiate.

Page is associated with the AbilitySlice life cycle

When AbilitySlice is in the foreground and has focus, its lifecycle state changes with the lifecycle state of the Page to which it belongs. When a Page has multiple AbilitySlice, for example: MyAbility has FooAbilitySlice and BarAbilitySlice. FooAbilitySlice is in the foreground and gets the focus, and will navigate to BarAbilitySlice. During this period, the life cycle status changes in the order of: Description The FooAbilitySlice status changed from ACTIVE to INACTIVE. BarAbilitySlice changes from INITIAL to INACTIVE and then to ACTIVE (assuming that BarAbilitySlice has not been started before). The FooAbilitySlice status changed from INACTIVE to BACKGROUND. Procedure The lifecycle method callbacks for the two slices are in the following order:

FooAbilitySlice.onInactive() –> BarAbilitySlice.onStart() –> BarAbilitySlice.onActive() –> FooAbilitySlice.onBackground()

Throughout the process, MyAbility remains ACTIVE. However, when a Page is destroyed by the system, all of its instantiated AbilitySlice will be destroyed in the same way, not just the front end AbilitySlice.

Navigation between AbilitySlice

Navigation within the same Page

When the AbilitySlice that initiated the navigation and the AbilitySlice of the navigation target are on the same Page, you can implement the navigation through the present() method. The following code snippet shows how to navigate to other AbilitySlice methods by clicking the button:

@Override
protected void onStart(Intent intent) {

    ...
    Button button = ...;
    button.setClickedListener(listener -> present(new TargetSlice(), newIntent())); . }Copy the code

The developer should use presentForResult() for navigation if he or she wants to be able to retrieve the result when the user returns from the navigation target, AbilitySlice. When the user returns from the navigation target AbilitySlice, the system will call onResult() to receive and process the returned result. The developer needs to override this method. The returned result is set by the navigation target AbilitySlice over its lifetime via setResult().

@Override
protected void onStart(Intent intent) {

    ...
    Button button = ...;
    button.setClickedListener(listener -> presentForResult(new TargetSlice(), new Intent(), 0)); . }@Override
protected void onResult(int requestCode, Intent resultIntent) {
    if (requestCode == 0) {
        // Process resultIntent here.}}Copy the code

The system maintains a AbilitySlice instance stack for each Page, and each AbilitySlice instance will be pushed into the foreground. When the developer calls present() or presentForResult() to an instance of AbilitySlice that already exists in the stack, AbilitySlice on top of that instance in the stack is offloaded and its life cycle is terminated. In the previous example code, the AbilitySlice instances specified in the navigation are all new, and even repeated execution of this code (in this case, these instances are the same class as the navigation target) will not cause any AbilitySlice to go out of the stack.

Navigation between different pages

AbilitySlice is an internal unit of a Page and is exposed in the form of an Action. Therefore, you can configure an Intent Action to navigate to the target AbilitySlice. Navigation between pages can be done using the startAbility() or startAbilityForResult() methods, and the callback to return the result is onAbilityResult(). Calling setResult() in Ability sets the result to be returned. For details, see the example of starting an application based on other properties of Operation.

Migration across devices

Cross-device migration (migration for short) Pages can be migrated between different devices of the same user to facilitate seamless switching. For example, to migrate Page from device A to device B, perform the following steps:

  1. Page on device A requests migration.
  2. HarmonyOS handles the migration task and calls back to the save data method of Page on device A to store the data necessary for the migration.
  3. HarmonyOS starts the same Page on device B and calls back its recovery method. Developers can follow the detailed steps below to develop a Page with migration capabilities.
Implements the IAbilityContinuation interface

Note that an application may contain multiple pages, and you only need to implement the IAbilityContinuation interface in pages that support migration by doing the following. At the same time, this Page contains all AbilitySlice also need to implement this interface.

  1. onStartContinuation()

After the Page requests the migration, the system first calls back to this method, where the developer can decide whether the migration is currently available, for example, a pop-up that asks the user to confirm whether to start the migration. If onStartContinuation() returns true, the system calls back to this method, and the developer saves data that must be passed to another device in order to restore the Page state. 3. OnRestoreData () After the Page is saved on the source device, the system calls back this method on the target device, and the developer receives the data used to restore the Page state in the callback. Note that a Page on the target device restarts its life cycle regardless of how its boot mode is configured. The system calls back to this method before onStart(). 4. OnCompleteContinuation () Once the data recovery on the target device is complete, the system calls back this method on the Page on the source device to notify the application that the migration process has ended. This is where the developer can check whether the migration was successful and handle the actions of the end of the migration. For example, the application can terminate its life cycle after the migration is complete. 5. OnRemoteTerminated () if developers use continueAbilityReversibly () instead of continueAbility (), You can then perform a fallback on the source device using reverseContinueAbility(). In this scenario, the equivalent of the same Page (two instances) is running on two devices at the same time. After the migration is complete, if the Page on the target device terminates for any reason, the source Page receives the termination notification through this callback.

Request the migration

Can achieve IAbilityContinuation Page in its life cycle, call continueAbility () or continueAbilityReversibly migration () request. The difference is that a migration initiated through the latter can then be migrated back.

try {
    continueAbility();
} catch (IllegalStateException e) {
    // Maybe another continuation in progress.. }Copy the code

Take Page migration from device A to device B as an example. The detailed process is as follows:

  1. Page on device A requests migration.
  2. System callback device on A Page and all AbilitySlice AbilitySlice stack instance IAbilityContinuation. OnStartContinuation () method, to confirm whether the current can immediately transfer.
  3. If you can immediately transfer, then the system callback device on A Page and all AbilitySlice AbilitySlice stack instance IAbilityContinuation. OnSaveData () method, in order to save the migrated data recovery state must be.
  4. If the successful saving data, the system on the device B start the same Page, and restore AbilitySlice stack, then the callback IAbilityContinuation. OnRestoreData () method, passing previously saved data; This Page on device B then begins its lifecycle callback from onStart().
  5. System callback device on A Page and all AbilitySlice AbilitySlice stack instance IAbilityContinuation. OnCompleteContinuation () method, notify the data recovery is successful or not.
Request a property

Use the continueAbilityReversibly () request, after the completion of the migration and migrated on a source side device can initiate a property Page, so that the user activity returned to the equipment.

try {
    reverseContinueAbility();
} catch (IllegalStateException e) {
    // Maybe another continuation in progress.. }Copy the code

For example, after the Page is migrated from device A to device B and requests A rollback, the detailed process is as follows:

  1. Page on device A requests A rollback.
  2. System callback device B on Page and all AbilitySlice AbilitySlice stack instance IAbilityContinuation. OnStartContinuation () method, to confirm whether the current can immediately transfer.
  3. If it can immediately transfer system callback device B on Page and all AbilitySlice AbilitySlice stack instance IAbilityContinuation. OnSaveData () method, in order to save a property state must be to recover the data.
  4. If the successful saving data, the system restore AbilitySlice stack in the device on A Page, and then the callback IAbilityContinuation. OnRestoreData () method, passing previously saved data.
  5. If the data recovery is successful, the system terminates the Page life cycle on device B.