系统管理或用户操作等行为均会引起Page实例在其生命周期的不同状态之间进行转换。Ability类提供的回调机制能够让Page及时感知外界变化,从而正确地应对状态变化(比如释放资源),这有助于提升应用的性能和稳健性。
生命周期(百度百科)
生命周期就是指一个对象的生老病死。
生命周期(Life Cycle)的概念应用很广泛,特别是在政治、经济、环境、技术、社会等诸多领域经常出现,其基本涵义可以通俗地理解为“从摇篮到坟墓”(Cradle-to-Grave)的整个过程。对于某个产品而言,就是从自然中来回到自然中去的全过程,也就是既包括制造产品所需要的原材料的采集、加工等生产过程,也包括产品贮存、运输等流通过程,还包括产品的使用过程以及产品报废或处置等废弃回到自然过程,这个过程构成了一个完整的产品的生命周期。
1.Page的生命周期
Page Ability是主要负责页面交互的,所以Page有几个状态:可见,可交互,不可见,销毁等等。每一个状态,都有一个生命周期函数和它对应。Page生命周期的不同状态转换及其对应的回调如下图所示:
1.onStart()
当系统首次创建Page实例时,触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后将进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。
@Override
publicvoidonStart(Intentintent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.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的可能原因包括以下几个方面:
- 用户通过系统管理能力关闭指定Page,例如使用任务管理器关闭Page。
- 用户行为触发Page的terminateAbility()方法调用,例如使用应用的退出功能。
- 配置变更导致系统暂时销毁Page并重建。
- 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。
2.AbilitySlice生命周期
AbilitySlice作为Page的组成单元,其生命周期是依托于其所属Page生命周期的。AbilitySlice和Page具有相同的生命周期状态和同名的回调,当Page生命周期发生变化时,它的AbilitySlice也会发生相同的生命周期变化。此外,AbilitySlice还具有独立于Page的生命周期变化,这发生在同一Page中的AbilitySlice之间导航时,此时Page的生命周期状态不会改变。
AbilitySlice生命周期回调与Page的相应回调类似,因此不再赘述。由于AbilitySlice承载具体的页面,开发者必须重写AbilitySlice的onStart()回调,并在此方法中通过setUIContent()方法设置页面,如下所示:
@Override
protectedvoidonStart(Intentintent) {
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,在此期间的生命周期状态变化顺序为:
- FooAbilitySlice从ACTIVE状态变为INACTIVE状态。
- BarAbilitySlice则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前BarAbilitySlice未曾启动)。
- FooAbilitySlice从INACTIVE状态变为BACKGROUND状态。
对应两个slice的生命周期方法回调顺序为:
FooAbilitySlice.onInactive() -->BarAbilitySlice.onStart() -->BarAbilitySlice.onActive() -->FooAbilitySlice.onBackground()
在整个流程中,MyAbility始终处于ACTIVE状态。但是,当Page被系统销毁时,其所有已实例化的AbilitySlice将联动销毁,而不仅是处于前台的AbilitySlice。
4.Page与AbilitySlice生命周期的例子
为了更好地理解Page与AbilitySlice的生命周期,我们将创建一个PageAndAbilitySliceLifeCycle
的应用作为演示。
此应用中包含两个Slice,MainAbilitySlice
和PayAbilitySlice
分别代表主页界面和支付界面
我们运行项目首先创建主页界面,主页界面的onStart()
和onActive()
方法分别调用,MainAbilitySlice
处于与用户交互的状态
用户点击跳转到支付界面,首先MainAbilitySlice
界面失去焦点,进入onInactive()
状态;马上创建了一个PayAbilitySlice
界面,onStart()
方法被调用,紧接着PayAbilitySlice
进入onActive()
状态,此时用户可见的是支付界面,而MainAbilitySlice
调用onBackground()
方法,此Slice不再对用户可见,通知开发者释放资源
在这个demo中,系统没有销毁MainAbilitySlice
,而是将其存入幕后不再让用户可见,因为我们可以看到日志台并没有打印onStop()
方法;也就是说我们每点击一次跳转,就创建一个新的Slice(调用onStart()
方法)。
这一次我们不点击跳转了,而是点击虚拟机上的返回按键,可以看到这一次打印了五条日志。首先PayAbilitySlice
失去焦点,进入onInactive
状态,而MainAbilitySlice
从后台资源中重新回到前台,(这里也再次证明了我们的MainAbilitySlice
是没有被销毁的)然后就如用户可见的onActive
状态;而用户不可见的PayAbilitySlice
调用onBackground
方法进入后台资源中,最终被onStop()
方法销毁,至此PayAbilitySlice
度过了它的一个生命周期
5.MainAbilitySlice
packagecom.hnucm.hmos0501_pageandabilityslicelifecycle.slice;
importcom.hnucm.hmos0501_pageandabilityslicelifecycle.ResourceTable;
importohos.aafwk.ability.AbilitySlice;
importohos.aafwk.content.Intent;
importohos.agp.components.Button;
importohos.hiviewdfx.HiLog;
importohos.hiviewdfx.HiLogLabel;
publicclassMainAbilitySliceextendsAbilitySlice {
staticfinalHiLogLabellabel=newHiLogLabel(HiLog.LOG_APP, 0x00201, "MainAbilitySlice"); //MY_MODULE=0x00201
@Override
publicvoidonStart(Intentintent) {
HiLog.info(label, "MainAbilitySlice---->onStart");
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
ButtontoPayBtn=findComponentById(ResourceTable.Id_toPayBtn);
toPayBtn.setClickedListener(listener->present(newPayAbilitySlice(),newIntent()));
}
@Override
protectedvoidonInactive() {
super.onInactive();
HiLog.info(label, "MainAbilitySlice---->onInactive");
}
@Override
protectedvoidonBackground() {
super.onBackground();
HiLog.info(label, "MainAbilitySlice---->onBackground");
}
@Override
protectedvoidonStop() {
super.onStop();
HiLog.info(label, "MainAbilitySlice---->onStop");
}
@Override
publicvoidonActive() {
super.onActive();
HiLog.info(label, "MainAbilitySlice---->onActive");
}
@Override
publicvoidonForeground(Intentintent) {
super.onForeground(intent);
HiLog.info(label, "MainAbilitySlice---->onForeground");
}
}
6.PayAbilitySlice
packagecom.hnucm.hmos0501_pageandabilityslicelifecycle.slice;
importcom.hnucm.hmos0501_pageandabilityslicelifecycle.ResourceTable;
importohos.aafwk.ability.AbilitySlice;
importohos.aafwk.content.Intent;
importohos.agp.components.Button;
importohos.hiviewdfx.HiLog;
importohos.hiviewdfx.HiLogLabel;
publicclassPayAbilitySliceextendsAbilitySlice {
staticfinalHiLogLabellabel=newHiLogLabel(HiLog.LOG_APP, 0x00201, "PayAbilitySlice"); //MY_MODULE=0x00201
@Override
publicvoidonStart(Intentintent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_pay);
HiLog.info(label, "PayAbilitySlice---->onStart");
ButtonbackMainBtn=findComponentById(ResourceTable.Id_backMainBtn);
backMainBtn.setClickedListener(listener->present(newMainAbilitySlice(),newIntent()));
}
@Override
publicvoidonActive() {
super.onActive();
HiLog.info(label, "PayAbilitySlice---->onActive");
}
@Override
protectedvoidonInactive() {
super.onInactive();
HiLog.info(label, "PayAbilitySlice---->onInactive");
}
@Override
protectedvoidonBackground() {
super.onBackground();
HiLog.info(label, "PayAbilitySlice---->onBackground");
}
@Override
protectedvoidonStop() {
super.onStop();
HiLog.info(label, "PayAbilitySlice---->onStop");
}
@Override
publicvoidonForeground(Intentintent) {
super.onForeground(intent);
HiLog.info(label, "PayAbilitySlice---->onForeground");
}
}