一、應(yīng)用生命周期(UIAbility)

生命周期說明
onCreate(want, launchParam): 當應(yīng)用啟動時,系統(tǒng)會首先調(diào)用onCreate方法。在這個階段,開發(fā)者可以初始化應(yīng)用所需的數(shù)據(jù)和資源。例如變量定義資源加載等,用于后續(xù)的UI展示。
onWindowStageCreate: UIAbility實例創(chuàng)建完成之后,在進入Foreground之前被調(diào)用。通常在這通過loadContent接口設(shè)置應(yīng)用要加載的頁面。
onNewWant: 當應(yīng)用的UIAbility實例已創(chuàng)建,且UIAbility配置為singleton啟動模式時,再次調(diào)用startAbility()方法啟動該UIAbility實例時,只會進入該UIAbility的onNewWant()回調(diào),不會進入其onCreate()和onWindowStageCreate()生命周期回調(diào)。應(yīng)用可以在該回調(diào)中更新要加載的資源和數(shù)據(jù)等,用于后續(xù)的UI展示。
onForeground: 當應(yīng)用從后臺切換到前臺時,onForeground方法會被調(diào)用??梢栽谶@重新申請系統(tǒng)需要的資源,在onBackground中釋放重新申請系統(tǒng)需要的資源。
onBackground: 當應(yīng)用從前臺切換到后臺時,onBackground方法會被觸發(fā)。在這個階段,可以釋放不再需要的資源、執(zhí)行一些后臺任務(wù)、保存狀態(tài)等。例如,地圖應(yīng)用在切換到后臺后,可以在onBackground回調(diào)中停止定位功能,以節(jié)省系統(tǒng)資源。
onWindowStageDestroy 在UIAbility實例銷毀之前時調(diào)用,可以在該回調(diào)中釋放UI資源。
onDestroy: 在UIAbility實例銷毀時觸發(fā)(殺進程才可觸發(fā),點擊返回鍵不會觸發(fā),也就是真正銷毀才會觸發(fā))。可以在回調(diào)中進行系統(tǒng)資源的釋放、數(shù)據(jù)的保存等操作。
代碼
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 當應(yīng)用啟動時,系統(tǒng)會首先調(diào)用onCreate方法。在這個階段,開發(fā)者可以初始化應(yīng)用所需的數(shù)據(jù)和資源。
// 例如變量定義資源加載等,用于后續(xù)的UI展示。
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// UIAbility實例創(chuàng)建完成之后,在進入Foreground之前被調(diào)用。
// 通常在這通過loadContent接口設(shè)置應(yīng)用要加載的頁面。
windowStage.loadContent('pages/Index', (err, data) => {
});
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam) {
// 當應(yīng)用的UIAbility實例已創(chuàng)建,且UIAbility配置為singleton模式時,再次調(diào)用startAbility()方法啟動該UIAbility實例時
// 可以在該回調(diào)中更新要加載的資源和數(shù)據(jù)等,用于后續(xù)的UI展示。
}
onForeground(): void {
// 當應(yīng)用從后臺切換到前臺時,onForeground方法會被調(diào)用。
// 可以在這重新申請系統(tǒng)需要的資源,在onBackground中釋放重新申請系統(tǒng)需要的資源。
}
onBackground(): void {
// 當應(yīng)用從前臺切換到后臺時,onBackground方法會被觸發(fā)。
// 在這個階段,可以釋放不再需要的資源、執(zhí)行一些后臺任務(wù)、保存狀態(tài)等。
// 例如,地圖應(yīng)用在切換到后臺后,可以在onBackground回調(diào)中停止定位功能,以節(jié)省系統(tǒng)資源。
}
onWindowStageDestroy() {
// UIAbility實例銷毀之前時調(diào)用,可以在該回調(diào)中釋放UI資源。
}
onDestroy() {
// UIAbility實例銷毀時觸發(fā)(殺進程才可觸發(fā),點擊返回鍵不會觸發(fā),也就是真正銷毀才會觸發(fā))??梢栽诨卣{(diào)中進行系統(tǒng)資源的釋放、數(shù)據(jù)的保存等操作。
}
}
二、組件導(dǎo)航Navigation頁面生命周期
Navigation是路由容器,他的生命周期都在NavDestination組件上。
NavDestination生命周期大致可分為三類:
- 自定義組件生命周期:aboutToAppear和aboutToDisappear
- 通用組件(Navigation、NavDestination共有)生命周期:OnAppear和OnDisAppear
- 自有生命周期:onWillAppear、onWillShow、onShown、onWillHide、onHidden、onWillDisappear

官網(wǎng):組件導(dǎo)航Navigation頁面生命周期
生命周期說明
- aboutToAppear:在創(chuàng)建自定義組件后,執(zhí)行其build()函數(shù)之前執(zhí)行(NavDestination創(chuàng)建之前),允許在該方法中改變狀態(tài)變量,更改將在后續(xù)執(zhí)行build()函數(shù)中生效。
- onWillAppear:NavDestination創(chuàng)建后,掛載到組件樹之前執(zhí)行,在該方法中更改狀態(tài)變量會在當前幀顯示生效。
- onAppear:通用生命周期事件,NavDestination組件掛載到組件樹時執(zhí)行。
- onWillShow:NavDestination組件布局顯示之前執(zhí)行,此時頁面不可見(應(yīng)用切換到前臺不會觸發(fā))。
- onShown:NavDestination組件布局顯示之后執(zhí)行,此時頁面已完成布局。
- onWillHide:NavDestination組件觸發(fā)隱藏之前執(zhí)行(應(yīng)用切換到后臺不會觸發(fā))。
- onHidden:NavDestination組件觸發(fā)隱藏后執(zhí)行(非棧頂頁面push進棧、棧頂頁面pop出棧、應(yīng)用切換到后臺都會觸發(fā))。
- onWillDisappear:NavDestination組件即將銷毀之前執(zhí)行,如果有轉(zhuǎn)場動畫,會在動畫前觸發(fā)(棧頂頁面pop出棧觸發(fā))。
- onDisAppear:通用生命周期事件,NavDestination組件從組件樹上卸載銷毀時執(zhí)行。
- aboutToDisappear:自定義組件析構(gòu)銷毀之前執(zhí)行,不允許在該方法中改變狀態(tài)變量。
Navigation頁面生命周期代碼
import { NavigationLifecycleComponent } from './NavigationLifecycleComponent';
/**
*組件導(dǎo)航Navigation頁面生命周期
*/
@Entry
@Component
struct NavigationLifecyclePage {
pathStack: NavPathStack = new NavPathStack()
aboutToAppear(): void {
console.log('Navigation--->頁面創(chuàng)建后掛樹的回調(diào):aboutToAppear');
this.pathStack.setInterception({
// 頁面跳轉(zhuǎn)前攔截,允許操作棧,在當前跳轉(zhuǎn)中生效。
willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
operation: NavigationOperation, animated: boolean) => {
if (typeof to === "string") {
console.log('Navigation--->頁面跳轉(zhuǎn)前回調(diào):NavPathStack::willShow 目標頁面:首頁');
} else {
let target: NavDestinationContext = to as NavDestinationContext;
console.log('Navigation--->頁面跳轉(zhuǎn)前回調(diào):NavPathStack::willShow 目標頁面:' + target.pathInfo.name);
}
},
// 頁面跳轉(zhuǎn)后回調(diào),在該回調(diào)中操作棧在下一次跳轉(zhuǎn)中刷新。
didShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
operation: NavigationOperation, isAnimated: boolean) => {
if (typeof from === "string") {
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow 首頁觸發(fā)跳轉(zhuǎn)');
} else {
let target: NavDestinationContext = from as NavDestinationContext;
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow ' + target.pathInfo.name + "觸發(fā)跳轉(zhuǎn)");
}
if (typeof to === "string") {
// 可以在當前執(zhí)行Navigation首頁數(shù)據(jù)更新
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow 跳轉(zhuǎn)到:首頁');
} else {
let target: NavDestinationContext = to as NavDestinationContext;
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow 跳轉(zhuǎn)到:' + target.pathInfo.name);
}
},
// Navigation單雙欄顯示狀態(tài)發(fā)生變更時觸發(fā)該回調(diào)。
modeChange: (mode: NavigationMode) => {
console.log('Navigation--->Navigation單雙欄顯示狀態(tài)發(fā)生變更時回調(diào):NavPathStack::modeChange ' + mode);
}
})
}
build() {
Navigation(this.pathStack) {
Column() {
Text("組件導(dǎo)航Navigation頁面生命周期")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 50 })
NavigationLifecycleComponent().margin({ top: 20 })
Button('組件導(dǎo)航NavDestination')
.fontSize(20)
.width('100%')
.margin({ top: 20 })
.onClick(() => {
this.pathStack.pushPathByName("NavDestinationLifecyclePage", null)
})
}
.height('100%')
.width('100%')
}
.mode(NavigationMode.Stack)
.onAppear(() => {
console.log('Navigation--->組件掛載到組件樹時回調(diào):onAppear');
})
.onDisAppear(() => {
console.log('Navigation--->組件從組件樹上卸載銷毀時回調(diào):onDisAppear');
})
}
// 頁面顯示時的回調(diào),如:后臺顯示,其他頁面返回
onPageShow(): void {
console.log('Navigation--->頁面顯示時的回調(diào):onPageShow');
}
// 頁面隱藏時的回調(diào),如:切到后臺,關(guān)閉頁面
onPageHide(): void {
console.log('Navigation--->頁面隱藏時的回調(diào):onPageHide');
}
// 頁面銷毀前下樹的回調(diào)
aboutToDisappear(): void {
console.log('Navigation--->頁面銷毀前下樹的回調(diào):aboutToDisappear');
}
}
NavDestination頁面生命周期
import { RouterLifecycleComponent } from './RouterLifecycleComponent';
import { router } from '@kit.ArkUI';
@Builder
export function NavDestinationLifecyclePageBuilder() {
NavDestinationLifecyclePage()
}
/**
*組件導(dǎo)航NavDestination頁面生命周期
*/
@Entry
@Component
struct NavDestinationLifecyclePage {
pathStack: NavPathStack = new NavPathStack()
aboutToAppear(): void {
console.log('Navigation--->NavDestination頁面創(chuàng)建后掛樹的回調(diào):aboutToAppear');
}
build() {
NavDestination() {
Column() {
Text("組件導(dǎo)航NavDestination頁面生命周期")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 50 })
RouterLifecycleComponent().margin({ top: 20 })
Button('組件導(dǎo)航NavDestination子頁面')
.fontSize(20)
.width('100%')
.margin({ top: 20 })
.onClick(() => {
this.pathStack.pushPathByName("NavDestinationLifecyclePage", null)
})
}
.height('100%')
.width('100%')
}
.title("組件導(dǎo)航NavDestination")
.onWillAppear(() => {
console.log('Navigation--->NavDestination創(chuàng)建后,掛載到組件樹之前回調(diào):onWillAppear');
})
.onReady((context: NavDestinationContext) => {
console.log('Navigation--->NavDestination頁面即將構(gòu)建子組件之前回調(diào):onReady');
this.pathStack = context.pathStack
})
.onAppear(() => {
console.log('Navigation--->NavDestination組件掛載到組件樹時回調(diào):onAppear');
})
.onWillShow(() => {
console.log('Navigation--->NavDestination組件布局顯示之前回調(diào):onWillShow');
})
.onShown(() => {
console.log('Navigation--->NavDestination組件布局顯示之后回調(diào):onShown');
})
.onWillHide(() => {
console.log('Navigation--->NavDestination組件觸發(fā)隱藏之前回調(diào):onWillHide');
})
.onHidden(() => {
console.log('Navigation--->NavDestination組件觸發(fā)隱藏后回調(diào):onHidden');
})
.onWillDisappear(() => {
console.log('Navigation--->NavDestination組件即將銷毀之前回調(diào):onWillDisappear');
})
.onDisAppear(() => {
console.log('Navigation--->NavDestination組件從組件樹上卸載銷毀時回調(diào):onDisAppear');
})
}
// 頁面顯示時的回調(diào),如:后臺顯示,其他頁面返回
onPageShow(): void {
console.log('Navigation--->NavDestination頁面顯示時的回調(diào):onPageShow');
}
// 頁面隱藏時的回調(diào),如:切到后臺,關(guān)閉頁面
onPageHide(): void {
console.log('Navigation--->NavDestination頁面隱藏時的回調(diào):onPageHide');
}
// 頁面銷毀前下樹的回調(diào)
aboutToDisappear(): void {
console.log('Navigation--->NavDestination頁面銷毀前下樹的回調(diào):aboutToDisappear');
}
}
額外說明
NavDestination(子頁面)返回到 Navigation(首頁)頁面生命周期onPageShow不會執(zhí)行。
可以使用其他兩種方式實現(xiàn),不確定有沒有更優(yōu)解,提供兩個思路給大家參考
- 使用觀察者模式,具體實現(xiàn)網(wǎng)上官網(wǎng)都有哈
- 使用NavPathStack. setInterception監(jiān)聽方式,里面有兩個函數(shù)willShow、didShow都能實現(xiàn)
pathStack: NavPathStack = new NavPathStack()
aboutToAppear(): void {
console.log('Navigation--->頁面創(chuàng)建后掛樹的回調(diào):aboutToAppear');
this.pathStack.setInterception({
// 頁面跳轉(zhuǎn)前攔截,允許操作棧,在當前跳轉(zhuǎn)中生效。
willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
operation: NavigationOperation, animated: boolean) => {
if (typeof to === "string") {
console.log('Navigation--->頁面跳轉(zhuǎn)前回調(diào):NavPathStack::willShow 目標頁面:首頁');
} else {
let target: NavDestinationContext = to as NavDestinationContext;
console.log('Navigation--->頁面跳轉(zhuǎn)前回調(diào):NavPathStack::willShow 目標頁面:' + target.pathInfo.name);
}
},
// 頁面跳轉(zhuǎn)后回調(diào),在該回調(diào)中操作棧在下一次跳轉(zhuǎn)中刷新。
didShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
operation: NavigationOperation, isAnimated: boolean) => {
if (typeof from === "string") {
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow 首頁觸發(fā)跳轉(zhuǎn)');
} else {
let target: NavDestinationContext = from as NavDestinationContext;
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow ' + target.pathInfo.name + "觸發(fā)跳轉(zhuǎn)");
}
if (typeof to === "string") {
// 可以在當前執(zhí)行Navigation首頁數(shù)據(jù)更新
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow 跳轉(zhuǎn)到:首頁');
} else {
let target: NavDestinationContext = to as NavDestinationContext;
console.log('Navigation--->頁面跳轉(zhuǎn)后回調(diào):NavPathStack::didShow 跳轉(zhuǎn)到:' + target.pathInfo.name);
}
},
// Navigation單雙欄顯示狀態(tài)發(fā)生變更時觸發(fā)該回調(diào)。
modeChange: (mode: NavigationMode) => {
console.log('Navigation--->Navigation單雙欄顯示狀態(tài)發(fā)生變更時回調(diào):NavPathStack::modeChange ' + mode);
}
})
}
三、自定義組件生命周期
自定義組件和頁面的關(guān)系
自定義組件5:@Component裝飾的UI單元,可以組合多個系統(tǒng)組件實現(xiàn)UI的復(fù)用,可以調(diào)用組件的生命周期。
頁面:即應(yīng)用的UI頁面??梢杂梢粋€或者多個自定義組件組成,@Entry裝飾的自定義組件為頁面的入口組件,即頁面的根節(jié)點,一個頁面有且僅能有一個@Entry。只有被@Entry裝飾的組件才可以調(diào)用頁面的生命周期。

生命周期說明
- aboutToAppear:組件即將出現(xiàn)時回調(diào)該接口,具體時機為在創(chuàng)建自定義組件的新實例后,在執(zhí)行其build()函數(shù)之前執(zhí)行。
- onDidBuild:組件build()函數(shù)執(zhí)行完成之后回調(diào)該接口,開發(fā)者可以在這個階段進行埋點數(shù)據(jù)上報等不影響實際UI的功能。不建議在onDidBuild函數(shù)中更改狀態(tài)變量、使用animateTo等功能,這可能會導(dǎo)致不穩(wěn)定的UI表現(xiàn)。
- aboutToDisappear:aboutToDisappear函數(shù)在自定義組件析構(gòu)銷毀之前執(zhí)行。不允許在aboutToDisappear函數(shù)中改變狀態(tài)變量,特別是@Link變量的修改可能會導(dǎo)致應(yīng)用程序行為不穩(wěn)定。
@Component
export struct NavDestinationLifecycleComponent {
aboutToAppear(): void {
console.log('Navigation--->NavDestination自定義組件即將出現(xiàn)時回調(diào):aboutToAppear');
}
build() {
Column() {
Text("組件導(dǎo)航NavDestination自定義組件生命周期")
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Orange)
}
.width('100%')
}
onDidBuild(): void {
console.log('Navigation--->NavDestination自定義組件build()函數(shù)執(zhí)行完成之后回調(diào):onDidBuild');
}
aboutToDisappear(): void {
console.log('Navigation--->NavDestination自定義組件析構(gòu)銷毀之前執(zhí)行:aboutToDisappear');
}
}
四、頁面路由Router生命周期
Router頁面生命周期為@Entry頁面中的通用方法,主要有如下四個生命周期:

頁面
import { RouterLifecycleComponent } from './RouterLifecycleComponent';
import { router } from '@kit.ArkUI';
/**
*頁面路由Router生命周期
*/
@Entry
@Component
struct RouterLifecyclePage {
aboutToAppear(): void {
console.log('Router--->頁面創(chuàng)建后掛樹的回調(diào):aboutToAppear');
}
build() {
Column() {
Text("頁面路由Router生命周期")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 50 })
RouterLifecycleComponent().margin({ top: 20 })
Button('頁面路由Router子頁面')
.fontSize(20)
.width('100%')
.margin({ top: 20 })
.onClick(() => {
router.pushUrl({ url: "pages/demo/RouterLifecyclePage" })
})
}
.height('100%')
.width('100%')
}
// 頁面顯示時的回調(diào),如:后臺顯示,其他頁面返回
onPageShow(): void {
console.log('Router--->頁面顯示時的回調(diào):onPageShow');
}
// 頁面隱藏時的回調(diào),如:切到后臺,關(guān)閉頁面
onPageHide(): void {
console.log('Router--->頁面隱藏時的回調(diào):onPageHide');
}
// 頁面銷毀前下樹的回調(diào)
aboutToDisappear(): void {
console.log('Router--->頁面銷毀前下樹的回調(diào):aboutToDisappear');
}
}
自定義組件
@Component
export struct RouterLifecycleComponent {
aboutToAppear(): void {
console.log('Router--->自定義組件即將出現(xiàn)時回調(diào):aboutToAppear');
}
build() {
Column() {
Text("頁面路由Router自定義組件生命周期")
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Orange)
}
.width('100%')
}
onDidBuild(): void {
console.log('Router--->自定義組件build()函數(shù)執(zhí)行完成之后回調(diào):onDidBuild');
}
aboutToDisappear(): void {
console.log('Router--->自定義組件析構(gòu)銷毀之前執(zhí)行:aboutToDisappear');
}
}
五、推薦使用組件導(dǎo)航Navigation原因
組件導(dǎo)航(Navigation)和頁面路由(@ohos.router)均支持應(yīng)用內(nèi)的頁面跳轉(zhuǎn),但組件導(dǎo)航支持在組件內(nèi)部進行跳轉(zhuǎn),使用更靈活。組件導(dǎo)航具備更強的一次開發(fā)多端部署能力,可以進行更加靈活的頁面棧操作,同時支持更豐富的動效和生命周期。因此,推薦使用組件導(dǎo)航(Navigation)來實現(xiàn)頁面跳轉(zhuǎn)以及組件內(nèi)的跳轉(zhuǎn),以獲得更佳的使用體驗。