鸿蒙开发之Page Ability生命周期

Page Ability生命周期概述

系统管理或用户操作等行为均会引起Page实例在其生命周期的不同状态之间进行转换。Ability类提供的回调机制能够让Page及时感知外界变化,从而正确地应对状态变化(比如释放资源),这有助于提升应用的性能和稳健性。

1.Page生命周期回调

Page生命周期的不同状态转换及其对应的回调示意图
在这里插入图片描述
1.onStart()

当系统首次创建Page实例时,触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后将进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。

 @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(FooSlice.class.getName());
    }

2.onActive()

Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用onInactive()回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用onActive()回调。因此,开发者通常需要成对实现onActive()和onInactive(),并在onActive()中获取在onInactive()中被释放的资源。

3.onInactive()

当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。

4.onBackground()

如果Page不再对用户可见,系统将调用此回调通知开发者用户进行相应的资源释放,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。

5.onForeground()

处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用onForeground()回调通知开发者,而后Page的生命周期状态回到INACTIVE状态。开发者应当在此回调中重新申请在onBackground()中释放的资源,最后Page的生命周期状态进一步回到ACTIVE状态,系统将通过onActive()回调通知开发者用户。

6.onStop()

系统将要销毁Page时,将会触发此回调函数,通知用户进行系统资源的释放。销毁Page的可能原因包括以下几个方面:

 1. 用户通过系统管理能力关闭指定Page,例如使用任务管理器关闭Page。
 2. 用户行为触发Page的terminateAbility()方法调用,例如使用应用的退出功能。
 3. 配置变更导致系统暂时销毁Page并重建。 	
 4. 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。

2.AbilitySlice生命周期

AbilitySlice作为Page的组成单元,其生命周期是依托于其所属Page生命周期的。AbilitySlice和Page具有相同的生命周期状态和同名的回调,当Page生命周期发生变化时,它的AbilitySlice也会发生相同的生命周期变化。此外,AbilitySlice还具有独立于Page的生命周期变化,这发生在同一Page中的AbilitySlice之间导航时,此时Page的生命周期状态不会改变。

AbilitySlice生命周期回调与Page的相应回调类似,因此不再赘述。由于AbilitySlice承载具体的页面,必须重写AbilitySlice的onStart()回调,并在此方法中通过setUIContent()方法设置页面。

 @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
 
        setUIContent(ResourceTable.Layout_main_layout);
    }

AbilitySlice实例创建和管理通常由应用负责,系统仅在特定情况下会创建AbilitySlice实例。例如,通过导航启动某个AbilitySlice时,是由系统负责实例化;但是在同一个Page中不同的AbilitySlice间导航时则由应用负责实例化。

3.Page与AbilitySlice生命周期

当AbilitySlice处于前台且具有焦点时,其生命周期状态随着所属Page的生命周期状态的变化而变化。当一个Page拥有多个AbilitySlice时,例如:MyAbility下有FooAbilitySlice和BarAbilitySlice,当前FooAbilitySlice处于前台并获得焦点,并即将导航到BarAbilitySlice,在此期间的生命周期状态变化顺序为:

 1. FooAbilitySlice从ACTIVE状态变为INACTIVE状态。

 2. BarAbilitySlice则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前BarAbilitySlice未曾启动)。

 3. FooAbilitySlice从INACTIVE状态变为BACKGROUND状态。

对应两个slice的生命周期方法回调顺序为:

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

在整个流程中,MyAbility始终处于ACTIVE状态。但是,当Page被系统销毁时,其所有已实例化的AbilitySlice将联动销毁,而不仅是处于前台的AbilitySlice。

生命周期测试

1.Page的生命周期

Page ---- MainAbility

public class MainAbility extends Ability {

    static final HiLogLabel LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00001, "MainAbility");

    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart");
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());
    }

    @Override
    protected void onActive() {
        HiLog.info(LOG_LABEL, "--------onActive");
        super.onActive();
    }

    @Override
    protected void onInactive() {
        HiLog.info(LOG_LABEL, "--------onInactive");
        super.onInactive();
    }


    @Override
    protected void onBackground() {
        HiLog.info(LOG_LABEL, "--------onBackground");
        super.onBackground();
    }

    @Override
    protected void onForeground(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onForeground");
        super.onForeground(intent);
    }

    @Override
    protected void onStop() {
        HiLog.info(LOG_LABEL, "--------onStop");
        super.onStop();
    }
}

abilitySlice ------ MainAbilitySlice

public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        Button button = (Button) findComponentById(ResourceTable.Id_button);
        button.setClickedListener(component -> {
           Intent intent1 = new Intent();
            ElementName elementName = new ElementName();
            elementName.setDeviceId("");
            elementName.setBundleName("com.example.myapplication");
            elementName.setAbilityName("MyAbility");
            intent1.setElement(elementName);
            startAbility(intent1);
        });

    }
}

Page ---- MyAbility

public class MyAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MyAbilitySlice.class.getName());
    }
}

abilitySlice ---- MyAbilitySlice


public class MyAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_my);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

1.当首次创建Page实例时
在这里插入图片描述

01-09 18:46:11.081 17234-17234/? I 00001/MainAbility: --------onStart
01-09 18:46:11.123 17234-17234/? I 00001/MainAbility: --------onActive

2.当点击跳转页面ability可见时并快速返回时

01-09 16:50:38.733 27131-27131/com.example.myapplication I 00001/MainAbility: --------onInactive
01-09 16:50:39.576 27131-27131/com.example.myapplication I 00001/MainAbility: --------onActive

3.当点击跳转页面ability完全不可见时
在这里插入图片描述

01-09 16:52:22.066 27131-27131/com.example.myapplication I 00001/MainAbility: --------onInactive
01-09 16:52:22.069 27131-27131/com.example.myapplication I 00001/MainAbility: --------onBackground

4.当返回最初创建ability时
在这里插入图片描述

01-09 16:53:59.607 27131-27131/com.example.myapplication I 00001/MainAbility: --------onForeground
01-09 16:53:59.608 27131-27131/com.example.myapplication I 00001/MainAbility: --------onActive

5.当ability正在结束或被销毁时
在这里插入图片描述

01-09 16:55:10.236 27131-27131/com.example.myapplication I 00001/MainAbility: --------onInactive
01-09 16:55:10.915 27131-27131/com.example.myapplication I 00001/MainAbility: --------onBackground
01-09 16:55:10.917 27131-27131/com.example.myapplication I 00001/MainAbility: --------onStop

2.AbilitySlice和Page具有相同的生命周期

abilitySlice ------ MainAbilitySlice

public class MainAbilitySlice extends AbilitySlice {
    static final HiLogLabel LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00002, "MainAbilitySlice");


    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart2");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        Button button = (Button) findComponentById(ResourceTable.Id_button);
        button.setClickedListener(component -> {
            Intent intent1 = new Intent();
            ElementName elementName = new ElementName();
            elementName.setDeviceId("");
            elementName.setBundleName("com.example.myapplication");
            elementName.setAbilityName("MyAbility");
            intent1.setElement(elementName);
            startAbility(intent1);
        });

    }

    @Override
    protected void onActive() {
        HiLog.info(LOG_LABEL, "--------onActive2");
        super.onActive();
    }

    @Override
    protected void onInactive() {
        HiLog.info(LOG_LABEL, "--------onInactive2");
        super.onInactive();
    }


    @Override
    protected void onBackground() {
        HiLog.info(LOG_LABEL, "--------onBackground2");
        super.onBackground();
    }

    @Override
    protected void onForeground(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onForeground2");
        super.onForeground(intent);
    }

    @Override
    protected void onStop() {
        HiLog.info(LOG_LABEL, "--------onStop2");
        super.onStop();
    }
}

在这里插入图片描述

01-09 19:44:13.553 27964-27964/? I 00001/MainAbility: --------onStart
01-09 19:44:13.557 27964-27964/? I 00002/MainAbilitySlice: --------onStart2
01-09 19:44:13.591 27964-27964/? I 00001/MainAbility: --------onActive
01-09 19:44:13.591 27964-27964/? I 00002/MainAbilitySlice: --------onActive2
01-09 19:50:08.736 27964-27964/com.example.myapplication I 00001/MainAbility: --------onInactive
01-09 19:50:08.737 27964-27964/com.example.myapplication I 00002/MainAbilitySlice: --------onInactive2
01-09 19:50:09.475 27964-27964/com.example.myapplication I 00001/MainAbility: --------onBackground
01-09 19:50:09.476 27964-27964/com.example.myapplication I 00002/MainAbilitySlice: --------onBackground2
01-09 19:50:17.923 27964-27964/com.example.myapplication I 00001/MainAbility: --------onForeground
01-09 19:50:17.923 27964-27964/com.example.myapplication I 00002/MainAbilitySlice: --------onForeground2
01-09 19:50:17.926 27964-27964/com.example.myapplication I 00001/MainAbility: --------onActive
01-09 19:50:17.927 27964-27964/com.example.myapplication I 00002/MainAbilitySlice: --------onActive2

3.相同Page,不同AbilitySlice的生命周期

同一个Page下不同AbilitySlice间跳转,Page始终处于激活状态,不同AbilitySlice进行状态切换

MainAbility添加路由配置

    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart");
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());

        addActionRoute("AbilitySlice1",  AbilitySlice1.class.getName());
    }

config.json配置action

   "actions": [
              "action.system.home",
              "AbilitySlice1"
            ]

MainAbilitySlice修改点击事件的处理方法为AbilitySlice间的导航

    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart2");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        Button button = (Button) findComponentById(ResourceTable.Id_button);
        button.setClickedListener(component -> {
            present(new AbilitySlice1(), new Intent());
        });

    }

在这里插入图片描述

01-09 20:29:48.743 26026-26026/? I 00001/MainAbility: --------onStart
01-09 20:29:48.749 26026-26026/? I 00002/MainAbilitySlice: --------onStart2
01-09 20:29:48.783 26026-26026/? I 00001/MainAbility: --------onActive
01-09 20:29:48.783 26026-26026/? I 00002/MainAbilitySlice: --------onActive2

01-09 19:57:44.206 27970-27970/com.example.myapplication I 00002/MainAbilitySlice: --------01-09 20:29:58.940 26026-26026/com.example.myapplication I 00002/MainAbilitySlice: --------onInactive2
01-09 20:29:58.940 26026-26026/com.example.myapplication I 00003/AbilitySlice1: --------onStart3
01-09 20:29:58.949 26026-26026/com.example.myapplication I 00003/AbilitySlice1: --------onActive3
01-09 20:29:58.949 26026-26026/com.example.myapplication I 00002/MainAbilitySlice: --------onBackground2

01-09 20:30:17.088 26026-26026/com.example.myapplication I 00003/AbilitySlice1: --------onInactive3
01-09 20:30:17.088 26026-26026/com.example.myapplication I 00002/MainAbilitySlice: --------onForeground2
01-09 20:30:17.091 26026-26026/com.example.myapplication I 00002/MainAbilitySlice: --------onActive2
01-09 20:30:17.091 26026-26026/com.example.myapplication I 00003/AbilitySlice1: --------onBackground3
01-09 20:30:17.091 26026-26026/com.example.myapplication I 00003/AbilitySlice1: --------onStop3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeDevMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值