鴻蒙 HarmonyOS 生命周期詳解,都在這里了

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

應(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)資源。

  • onWindowStageDestroyUIAbility實例銷毀之前時調(diào)用,可以在該回調(diào)中釋放UI資源。

  • onDestroy: 在UIAbility實例銷毀時觸發(fā)(殺進程才可觸發(fā),點擊返回鍵不會觸發(fā),也就是真正銷毀才會觸發(fā))。可以在回調(diào)中進行系統(tǒng)資源的釋放、數(shù)據(jù)的保存等操作。

官方:應(yīng)用生命周期(UIAbility)

代碼

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生命周期大致可分為三類:

  1. 自定義組件生命周期:aboutToAppearaboutToDisappear
  2. 通用組件(Navigation、NavDestination共有)生命周期:OnAppearOnDisAppear
  3. 自有生命周期:onWillAppear、onWillShow、onShown、onWillHide、onHidden、onWillDisappear
組件導(dǎo)航Navigation頁面生命周期

官網(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');
  }
}

官網(wǎng):頁面和自定義組件生命周期

四、頁面路由Router生命周期

Router頁面生命周期為@Entry頁面中的通用方法,主要有如下四個生命周期:

頁面路由Router生命周期

頁面

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),以獲得更佳的使用體驗。

具體可以查看官網(wǎng)說明

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容