ArkTS 中页面和组件的生命周期

📌 快速概览

在 HarmonyOS ArkTS 中,生命周期是指页面、组件从创建到销毁的整个过程中,系统自动调用的一系列钩子函数。理解生命周期对于正确管理资源、优化性能至关重要。


🎯 一、生命周期分类

1.1 三个层级的生命周期

层级 说明 典型场景
UIAbility 生命周期 应用的 Ability 级别生命周期 应用启动、后台、销毁
页面生命周期 页面级别的生命周期 页面显示、隐藏、返回
组件生命周期 自定义组件级别的生命周期 组件创建、更新、销毁

1.2 生命周期概览图

UIAbility 生命周期
├── onCreate()              // Ability 创建
├── onWindowStageCreate()   // 窗口舞台创建
├── onForeground()          // 进入前台
├── onBackground()          // 进入后台
└── onDestroy()             // Ability 销毁

页面生命周期
├── onPageShow()            // 页面显示
├── onPageHide()            // 页面隐藏
└── onBackPress()           // 返回按钮

组件生命周期
├── aboutToAppear()         // 组件即将出现
├── aboutToDisappear()      // 组件即将消失
└── aboutToReuse()          // 组件复用(@Reusable)

📖 二、UIAbility 生命周期

2.1 生命周期钩子

钩子函数 调用时机 用途
onCreate() Ability 首次创建 初始化全局数据
onWindowStageCreate() 窗口舞台创建 加载首页
onForeground() 进入前台 恢复暂停的任务
onBackground() 进入后台 暂停任务、保存数据
onWindowStageDestroy() 窗口舞台销毁 释放窗口资源
onDestroy() Ability 销毁 释放资源

2.2 生命周期流程

正常启动流程
应用启动
   ↓
onCreate()                    // 创建 Ability
   ↓
onWindowStageCreate()         // 创建窗口舞台,加载首页
   ↓
onForeground()                // 进入前台
   ↓
应用运行中
   ↓
(用户按 Home 键)
   ↓
onBackground()                // 进入后台
   ↓
(用户重新打开应用)
   ↓
onForeground()                // 重新进入前台
   ↓
(用户关闭应用)
   ↓
onWindowStageDestroy()        // 销毁窗口舞台
   ↓
onDestroy()                   // 销毁 Ability

2.3 代码示例

// EntryAbility.ets
import UIAbility from "@ohos.app.ability.UIAbility";
import window from "@ohos.window";
import Want from "@ohos.app.ability.Want";

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
    console.info("[EntryAbility] onCreate");

    // ✅ 初始化全局数据
    AppStorage.SetOrCreate("userId", "");
    AppStorage.SetOrCreate("token", "");

    // ✅ 检查登录状态
    this.checkLoginStatus();
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    console.info("[EntryAbility] onWindowStageCreate");

    // ✅ 加载首页
    windowStage.loadContent("pages/Index", (err, data) => {
      if (err.code) {
        console.error("加载页面失败:", err.message);
        return;
      }
      console.info("加载页面成功");
    });
  }

  onForeground() {
    console.info("[EntryAbility] onForeground");

    // ✅ 恢复定时器
    this.startTimer();

    // ✅ 刷新数据
    this.refreshData();
  }

  onBackground() {
    console.info("[EntryAbility] onBackground");

    // ✅ 停止定时器
    this.stopTimer();

    // ✅ 保存数据
    this.saveData();
  }

  onWindowStageDestroy() {
    console.info("[EntryAbility] onWindowStageDestroy");

    // ✅ 释放窗口资源
    this.releaseWindowResources();
  }

  onDestroy() {
    console.info("[EntryAbility] onDestroy");

    // ✅ 释放全局资源
    this.releaseResources();

    // ✅ 取消订阅
    this.unsubscribeAll();
  }

  // 辅助方法
  async checkLoginStatus() {
    const token = await storage.get("token");
    if (token) {
      AppStorage.SetOrCreate("token", token);
    }
  }

  startTimer() {
    // 启动定时器
  }

  stopTimer() {
    // 停止定时器
  }

  refreshData() {
    // 刷新数据
  }

  saveData() {
    // 保存数据
  }

  releaseWindowResources() {
    // 释放窗口资源
  }

  releaseResources() {
    // 释放资源
  }

  unsubscribeAll() {
    // 取消所有订阅
  }
}

📖 三、页面生命周期

3.1 生命周期钩子

钩子函数 调用时机 用途
onPageShow() 页面显示时 启动动画、刷新数据
onPageHide() 页面隐藏时 停止动画、暂停任务
onBackPress() 用户按返回键时 拦截返回、显示确认对话框

3.2 生命周期流程

页面跳转流程
页面 A(当前页面)
   ↓
(跳转到页面 B)
   ↓
页面 A: onPageHide()          // 页面 A 隐藏
   ↓
页面 B: aboutToAppear()       // 页面 B 组件即将出现
   ↓
页面 B: onPageShow()          // 页面 B 显示
   ↓
(用户按返回键)
   ↓
页面 B: onBackPress()         // 返回拦截(可选)
   ↓
页面 B: onPageHide()          // 页面 B 隐藏
   ↓
页面 B: aboutToDisappear()    // 页面 B 组件即将消失
   ↓
页面 A: onPageShow()          // 页面 A 重新显示

3.3 代码示例

基本用法
// pages/Index.ets
@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  private timer: number = -1

  onPageShow() {
    console.info('[Index] onPageShow - 页面显示')

    // ✅ 启动定时器
    this.timer = setInterval(() => {
      console.info('定时任务执行')
    }, 1000)

    // ✅ 刷新数据
    this.loadData()

    // ✅ 启动动画
    this.startAnimation()
  }

  onPageHide() {
    console.info('[Index] onPageHide - 页面隐藏')

    // ✅ 停止定时器
    if (this.timer !== -1) {
      clearInterval(this.timer)
      this.timer = -1
    }

    // ✅ 停止动画
    this.stopAnimation()
  }

  onBackPress(): boolean | void {
    console.info('[Index] onBackPress - 按下返回键')

    // ✅ 显示退出确认对话框
    AlertDialog.show({
      title: '提示',
      message: '确定要退出应用吗?',
      primaryButton: {
        value: '确定',
        action: () => {
          // 退出应用
          this.context.terminateSelf()
        }
      },
      secondaryButton: {
        value: '取消',
        action: () => {
          console.info('用户取消退出')
        }
      }
    })

    // ✅ 返回 true 表示拦截返回事件
    return true
  }

  build() {
    Column() {
      Text(this.message)
        .fontSize(24)
    }
    .width('100%')
    .height('100%')
  }

  // 辅助方法
  async loadData() {
    // 加载数据
  }

  startAnimation() {
    // 启动动画
  }

  stopAnimation() {
    // 停止动画
  }
}

onBackPress 拦截返回
@Entry
@Component
struct FormPage {
  @State formData: string = ''
  @State isModified: boolean = false

  onBackPress(): boolean | void {
    // ✅ 如果表单已修改,提示保存
    if (this.isModified) {
      AlertDialog.show({
        title: '提示',
        message: '表单尚未保存,确定要离开吗?',
        primaryButton: {
          value: '保存并离开',
          action: () => {
            this.saveForm().then(() => {
              router.back()
            })
          }
        },
        secondaryButton: {
          value: '不保存',
          action: () => {
            router.back()
          }
        }
      })

      // 拦截返回
      return true
    }

    // ✅ 表单未修改,允许返回
    // 返回 false 或不返回值,表示不拦截
    return false
  }

  build() {
    Column() {
      TextInput({ text: this.formData })
        .onChange((value: string) => {
          this.formData = value
          this.isModified = true
        })

      Button('保存')
        .onClick(() => {
          this.saveForm()
        })
    }
  }

  async saveForm() {
    // 保存表单数据
    console.info('保存表单')
    this.isModified = false
  }
}

📖 四、组件生命周期

4.1 生命周期钩子

钩子函数 调用时机 用途
aboutToAppear() 组件即将出现 初始化数据、订阅事件
aboutToDisappear() 组件即将消失 清理资源、取消订阅
aboutToReuse() 组件即将复用(@Reusable) 重置组件状态

4.2 生命周期流程

组件创建到销毁
组件创建
   ↓
constructor()                 // 构造函数(隐式)
   ↓
aboutToAppear()               // 组件即将出现
   ↓
build()                       // 构建 UI(首次)
   ↓
组件显示
   ↓
(状态变化)
   ↓
build()                       // 重新构建 UI
   ↓
(组件销毁)
   ↓
aboutToDisappear()            // 组件即将消失
   ↓
组件销毁

4.3 代码示例

基本用法
@Component
struct CounterComponent {
  @State count: number = 0
  private timer: number = -1

  aboutToAppear() {
    console.info('[CounterComponent] aboutToAppear - 组件即将出现')

    // ✅ 初始化数据
    this.loadInitialData()

    // ✅ 启动定时器
    this.timer = setInterval(() => {
      this.count++
    }, 1000)

    // ✅ 订阅事件
    eventHub.on('counterReset', this.resetCounter)
  }

  aboutToDisappear() {
    console.info('[CounterComponent] aboutToDisappear - 组件即将消失')

    // ✅ 清理定时器
    if (this.timer !== -1) {
      clearInterval(this.timer)
      this.timer = -1
    }

    // ✅ 取消订阅
    eventHub.off('counterReset', this.resetCounter)

    // ✅ 释放资源
    this.cleanup()
  }

  build() {
    Column() {
      Text(`计数: ${this.count}`)
        .fontSize(24)

      Button('重置')
        .onClick(() => {
          this.count = 0
        })
    }
  }

  // 辅助方法
  loadInitialData() {
    console.info('加载初始数据')
  }

  resetCounter = () => {
    this.count = 0
  }

  cleanup() {
    console.info('清理资源')
  }
}

父子组件生命周期
// 父组件
@Entry
@Component
struct ParentComponent {
  @State showChild: boolean = true

  aboutToAppear() {
    console.info('[ParentComponent] aboutToAppear')
  }

  aboutToDisappear() {
    console.info('[ParentComponent] aboutToDisappear')
  }

  build() {
    Column() {
      Text('父组件')
        .fontSize(24)

      Button(this.showChild ? '隐藏子组件' : '显示子组件')
        .onClick(() => {
          this.showChild = !this.showChild
        })

      if (this.showChild) {
        ChildComponent()
      }
    }
  }
}

// 子组件
@Component
struct ChildComponent {
  aboutToAppear() {
    console.info('[ChildComponent] aboutToAppear')
  }

  aboutToDisappear() {
    console.info('[ChildComponent] aboutToDisappear')
  }

  build() {
    Text('子组件')
      .fontSize(20)
      .fontColor(Color.Blue)
  }
}

执行顺序

显示子组件:
ParentComponent: aboutToAppear
ParentComponent: build
ChildComponent: aboutToAppear
ChildComponent: build

隐藏子组件:
ChildComponent: aboutToDisappear
ParentComponent: build(重新构建)

@Reusable 组件复用
// 可复用组件
@Reusable
@Component
struct ReusableCard {
  @State title: string = ''
  @State content: string = ''

  aboutToAppear() {
    console.info('[ReusableCard] aboutToAppear')
    // 首次创建时调用
  }

  aboutToReuse(params: Record<string, Object>) {
    console.info('[ReusableCard] aboutToReuse')

    // ✅ 组件复用时调用,更新状态
    this.title = params.title as string
    this.content = params.content as string
  }

  aboutToDisappear() {
    console.info('[ReusableCard] aboutToDisappear')
    // 组件销毁时调用
  }

  build() {
    Column() {
      Text(this.title)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)

      Text(this.content)
        .fontSize(16)
    }
    .padding(15)
    .backgroundColor('#F5F5F5')
    .borderRadius(8)
  }
}

// 使用可复用组件
@Entry
@Component
struct CardList {
  @State cardData: CardItem[] = [
    { id: 1, title: '卡片 1', content: '内容 1' },
    { id: 2, title: '卡片 2', content: '内容 2' },
    { id: 3, title: '卡片 3', content: '内容 3' }
  ]

  build() {
    List() {
      ForEach(this.cardData, (item: CardItem) => {
        ListItem() {
          ReusableCard({
            title: item.title,
            content: item.content
          })
        }
      }, (item: CardItem) => item.id.toString())
    }
  }
}

class CardItem {
  id: number
  title: string
  content: string
}

📊 五、生命周期执行顺序

5.1 应用启动完整流程

1. UIAbility: onCreate()                    // Ability 创建
2. UIAbility: onWindowStageCreate()         // 窗口舞台创建
3. 页面组件: aboutToAppear()                // 页面组件即将出现
4. 子组件: aboutToAppear()                  // 子组件即将出现(从上到下)
5. 页面组件: build()                        // 构建 UI
6. 子组件: build()                          // 构建子组件 UI
7. 页面: onPageShow()                       // 页面显示
8. UIAbility: onForeground()                // 进入前台

5.2 页面跳转完整流程

从页面 A 跳转到页面 B:

1. 页面 A: onPageHide()                     // 页面 A 隐藏
2. 页面 B: aboutToAppear()                  // 页面 B 组件即将出现
3. 页面 B 子组件: aboutToAppear()           // 子组件即将出现
4. 页面 B: build()                          // 构建 UI
5. 页面 B: onPageShow()                     // 页面 B 显示

从页面 B 返回到页面 A:

1. 页面 B: onBackPress()                    // 返回拦截(可选)
2. 页面 B: onPageHide()                     // 页面 B 隐藏
3. 页面 B: aboutToDisappear()               // 页面 B 组件即将消失
4. 页面 B 子组件: aboutToDisappear()        // 子组件即将消失
5. 页面 A: onPageShow()                     // 页面 A 重新显示

5.3 应用后台/前台切换

进入后台:

1. 页面: onPageHide()                       // 页面隐藏
2. UIAbility: onBackground()                // 进入后台

重新进入前台:

1. UIAbility: onForeground()                // 进入前台
2. 页面: onPageShow()                       // 页面显示

5.4 应用销毁流程

1. 页面: onPageHide()                       // 页面隐藏
2. 页面组件: aboutToDisappear()             // 页面组件即将消失
3. 子组件: aboutToDisappear()               // 子组件即将消失(从下到上)
4. UIAbility: onBackground()                // 进入后台
5. UIAbility: onWindowStageDestroy()        // 窗口舞台销毁
6. UIAbility: onDestroy()                   // Ability 销毁

🎯 六、实际应用场景

6.1 场景 1:数据加载

@Entry
@Component
struct UserProfile {
  @State userInfo: UserInfo | null = null
  @State isLoading: boolean = true

  aboutToAppear() {
    console.info('[UserProfile] aboutToAppear')

    // ✅ 在组件即将出现时加载数据
    this.loadUserInfo()
  }

  onPageShow() {
    console.info('[UserProfile] onPageShow')

    // ✅ 每次页面显示时刷新数据
    this.refreshUserInfo()
  }

  build() {
    Column() {
      if (this.isLoading) {
        LoadingProgress()
          .width(50)
          .height(50)
      } else if (this.userInfo) {
        Text(`姓名: ${this.userInfo.name}`)
        Text(`年龄: ${this.userInfo.age}`)
      } else {
        Text('加载失败')
      }
    }
  }

  async loadUserInfo() {
    try {
      this.isLoading = true
      const userInfo = await UserService.getUserInfo()
      this.userInfo = userInfo
    } catch (error) {
      console.error('加载用户信息失败:', error.message)
    } finally {
      this.isLoading = false
    }
  }

  async refreshUserInfo() {
    // 静默刷新(不显示 loading)
    try {
      const userInfo = await UserService.getUserInfo()
      this.userInfo = userInfo
    } catch (error) {
      console.error('刷新用户信息失败:', error.message)
    }
  }
}

class UserInfo {
  name: string
  age: number
}

class UserService {
  static async getUserInfo(): Promise<UserInfo> {
    // 模拟网络请求
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve({ name: '张三', age: 25 })
      }, 1000)
    })
  }
}

6.2 场景 2:视频播放器

@Component
struct VideoPlayer {
  @State isPlaying: boolean = false
  private videoController: VideoController = new VideoController()

  aboutToAppear() {
    console.info('[VideoPlayer] aboutToAppear')

    // ✅ 初始化播放器
    this.initPlayer()
  }

  onPageShow() {
    console.info('[VideoPlayer] onPageShow')

    // ✅ 页面显示时恢复播放
    if (this.isPlaying) {
      this.videoController.start()
    }
  }

  onPageHide() {
    console.info('[VideoPlayer] onPageHide')

    // ✅ 页面隐藏时暂停播放
    if (this.isPlaying) {
      this.videoController.pause()
    }
  }

  aboutToDisappear() {
    console.info('[VideoPlayer] aboutToDisappear')

    // ✅ 释放播放器资源
    this.videoController.stop()
    this.releasePlayer()
  }

  build() {
    Column() {
      Video({
        src: 'https://example.com/video.mp4',
        controller: this.videoController
      })
        .width('100%')
        .height(300)

      Row() {
        Button(this.isPlaying ? '暂停' : '播放')
          .onClick(() => {
            if (this.isPlaying) {
              this.videoController.pause()
            } else {
              this.videoController.start()
            }
            this.isPlaying = !this.isPlaying
          })
      }
    }
  }

  initPlayer() {
    console.info('初始化播放器')
  }

  releasePlayer() {
    console.info('释放播放器资源')
  }
}

6.3 场景 3:定时器管理

@Component
struct CountdownTimer {
  @State countdown: number = 60
  private timer: number = -1

  aboutToAppear() {
    console.info('[CountdownTimer] aboutToAppear')

    // ✅ 启动倒计时
    this.startCountdown()
  }

  aboutToDisappear() {
    console.info('[CountdownTimer] aboutToDisappear')

    // ✅ 清理定时器
    this.stopCountdown()
  }

  build() {
    Column() {
      Text(`倒计时: ${this.countdown}`)
        .fontSize(24)

      if (this.countdown === 0) {
        Text('时间到!')
          .fontSize(20)
          .fontColor(Color.Red)
      }
    }
  }

  startCountdown() {
    this.timer = setInterval(() => {
      if (this.countdown > 0) {
        this.countdown--
      } else {
        this.stopCountdown()
      }
    }, 1000)
  }

  stopCountdown() {
    if (this.timer !== -1) {
      clearInterval(this.timer)
      this.timer = -1
    }
  }
}

6.4 场景 4:事件订阅

// 事件总线(简化版)
class EventBus {
  private static instance: EventBus = new EventBus()
  private events: Map<string, Function[]> = new Map()

  static getInstance(): EventBus {
    return this.instance
  }

  on(event: string, callback: Function) {
    if (!this.events.has(event)) {
      this.events.set(event, [])
    }
    this.events.get(event)!.push(callback)
  }

  off(event: string, callback: Function) {
    const callbacks = this.events.get(event)
    if (callbacks) {
      const index = callbacks.indexOf(callback)
      if (index > -1) {
        callbacks.splice(index, 1)
      }
    }
  }

  emit(event: string, data?: any) {
    const callbacks = this.events.get(event)
    if (callbacks) {
      callbacks.forEach(callback => callback(data))
    }
  }
}

// 使用事件订阅
@Component
struct NotificationListener {
  @State notifications: string[] = []
  private eventBus = EventBus.getInstance()

  aboutToAppear() {
    console.info('[NotificationListener] aboutToAppear')

    // ✅ 订阅事件
    this.eventBus.on('newNotification', this.handleNotification)
  }

  aboutToDisappear() {
    console.info('[NotificationListener] aboutToDisappear')

    // ✅ 取消订阅(防止内存泄漏)
    this.eventBus.off('newNotification', this.handleNotification)
  }

  build() {
    Column() {
      Text('通知列表')
        .fontSize(24)

      List() {
        ForEach(this.notifications, (notification: string, index: number) => {
          ListItem() {
            Text(`${index + 1}. ${notification}`)
          }
        }, (notification: string, index: number) => index.toString())
      }
    }
  }

  handleNotification = (notification: string) => {
    console.info('收到新通知:', notification)
    this.notifications.push(notification)
  }
}

// 发送通知
@Entry
@Component
struct NotificationSender {
  private eventBus = EventBus.getInstance()

  build() {
    Column() {
      Button('发送通知')
        .onClick(() => {
          this.eventBus.emit('newNotification', `通知 ${Date.now()}`)
        })

      Divider().margin(20)

      NotificationListener()
    }
  }
}

⚠️ 七、注意事项和最佳实践

7.1 资源管理

✅ 正确做法
@Component
struct ResourceComponent {
  private timer: number = -1
  private subscription: Subscription | null = null

  aboutToAppear() {
    // ✅ 在 aboutToAppear 中创建资源
    this.timer = setInterval(() => {
      console.info('定时任务')
    }, 1000)

    // ✅ 订阅事件
    this.subscription = eventBus.subscribe('event', this.handleEvent)
  }

  aboutToDisappear() {
    // ✅ 在 aboutToDisappear 中释放资源
    if (this.timer !== -1) {
      clearInterval(this.timer)
      this.timer = -1
    }

    // ✅ 取消订阅
    if (this.subscription) {
      this.subscription.unsubscribe()
      this.subscription = null
    }
  }

  build() {
    Text('资源管理示例')
  }

  handleEvent = () => {
    // 处理事件
  }
}

❌ 错误做法
@Component
struct BadResourceComponent {
  private timer: number = -1

  aboutToAppear() {
    // ✅ 创建定时器
    this.timer = setInterval(() => {
      console.info('定时任务')
    }, 1000)
  }

  // ❌ 忘记清理定时器,导致内存泄漏
  // aboutToDisappear() 中没有清理资源
}

7.2 异步操作

✅ 正确做法
@Component
struct AsyncComponent {
  @State data: string = ''
  private abortController: AbortController | null = null

  aboutToAppear() {
    // ✅ 使用 AbortController 管理异步请求
    this.abortController = new AbortController()

    this.loadData()
  }

  aboutToDisappear() {
    // ✅ 取消未完成的请求
    if (this.abortController) {
      this.abortController.abort()
      this.abortController = null
    }
  }

  async loadData() {
    try {
      const response = await fetch('https://api.example.com/data', {
        signal: this.abortController?.signal
      })
      const data = await response.json()
      this.data = data
    } catch (error) {
      if (error.name === 'AbortError') {
        console.info('请求已取消')
      } else {
        console.error('加载数据失败:', error.message)
      }
    }
  }

  build() {
    Text(this.data)
  }
}

7.3 状态初始化

✅ 正确做法
@Component
struct StateComponent {
  @State count: number = 0  // ✅ 在声明时初始化

  aboutToAppear() {
    // ✅ 在 aboutToAppear 中进行复杂的初始化
    this.loadInitialData()
  }

  build() {
    Text(`计数: ${this.count}`)
  }

  async loadInitialData() {
    // 加载初始数据
    const initialValue = await storage.get('count')
    if (initialValue !== null) {
      this.count = initialValue
    }
  }
}

❌ 错误做法
@Component
struct BadStateComponent {
  @State count: number  // ❌ 未初始化,运行时错误

  aboutToAppear() {
    this.count = 0  // ❌ 太晚了,应该在声明时初始化
  }

  build() {
    Text(`计数: ${this.count}`)
  }
}

7.4 父子组件通信

✅ 正确做法
// 父组件
@Entry
@Component
struct ParentComponent {
  @State parentData: string = '父组件数据'

  aboutToAppear() {
    console.info('[ParentComponent] aboutToAppear')
  }

  build() {
    Column() {
      // ✅ 通过 @Prop 传递数据给子组件
      ChildComponent({ childData: this.parentData })
    }
  }
}

// 子组件
@Component
struct ChildComponent {
  @Prop childData: string  // ✅ 使用 @Prop 接收数据

  aboutToAppear() {
    console.info('[ChildComponent] aboutToAppear')
    console.info('接收到的数据:', this.childData)
  }

  build() {
    Text(this.childData)
  }
}

7.5 生命周期中的性能优化

@Component
struct OptimizedComponent {
  @State data: DataItem[] = []
  private cache: Map<string, any> = new Map()

  aboutToAppear() {
    // ✅ 使用缓存避免重复加载
    if (this.cache.has('data')) {
      this.data = this.cache.get('data')
    } else {
      this.loadData()
    }
  }

  aboutToDisappear() {
    // ✅ 缓存数据供下次使用
    this.cache.set('data', this.data)
  }

  build() {
    List() {
      ForEach(this.data, (item: DataItem) => {
        ListItem() {
          Text(item.name)
        }
      }, (item: DataItem) => item.id)
    }
  }

  async loadData() {
    // 加载数据
  }
}

class DataItem {
  id: string
  name: string
}

🎓 八、快速参考

8.1 生命周期钩子速查表

层级 钩子函数 调用时机 常见用途
UIAbility onCreate() Ability 创建 全局初始化
UIAbility onWindowStageCreate() 窗口舞台创建 加载首页
UIAbility onForeground() 进入前台 恢复任务
UIAbility onBackground() 进入后台 暂停任务、保存数据
UIAbility onDestroy() Ability 销毁 释放资源
页面 onPageShow() 页面显示 刷新数据、启动动画
页面 onPageHide() 页面隐藏 停止动画、暂停任务
页面 onBackPress() 按下返回键 拦截返回
组件 aboutToAppear() 组件即将出现 初始化、订阅事件
组件 aboutToDisappear() 组件即将消失 清理资源、取消订阅
组件 aboutToReuse() 组件复用 更新状态

8.2 常见场景速查

场景 推荐钩子 说明
加载数据 aboutToAppear() 组件首次创建时加载
刷新数据 onPageShow() 每次页面显示时刷新
启动定时器 aboutToAppear() 组件创建时启动
停止定时器 aboutToDisappear() 组件销毁时停止
订阅事件 aboutToAppear() 组件创建时订阅
取消订阅 aboutToDisappear() 组件销毁时取消
播放视频 onPageShow() 页面显示时播放
暂停视频 onPageHide() 页面隐藏时暂停
保存数据 onBackground() 进入后台时保存
拦截返回 onBackPress() 显示确认对话框
释放资源 aboutToDisappear() 组件销毁时释放

8.3 常见错误速查

错误 原因 解决方案
内存泄漏 未清理定时器 aboutToDisappear() 中清理
异步请求未取消 组件销毁后仍在请求 使用 AbortController
状态未初始化 忘记初始化 @State 在声明时初始化
事件监听未移除 忘记取消订阅 aboutToDisappear() 中取消
数据未刷新 未在 onPageShow() 刷新 添加刷新逻辑

📌 九、总结

核心要点

  1. 三个层级:UIAbility、页面、组件,各有不同的生命周期
  2. 成对出现aboutToAppear() 对应 aboutToDisappear()
  3. 资源管理:在 aboutToAppear() 中创建,在 aboutToDisappear() 中释放
  4. 数据刷新:使用 onPageShow() 刷新页面数据
  5. 返回拦截:使用 onBackPress() 拦截返回事件

最佳实践

  1. 总是清理资源:定时器、订阅、网络请求
  2. 合理使用缓存:避免重复加载数据
  3. 异步操作要可取消:使用 AbortController
  4. 状态要初始化:在声明时初始化 @State
  5. 生命周期要配对:创建和销毁成对出现

记忆口诀

Ability 生命周期,六个钩子记心里
onCreate 初始化,onDestroy 来清理
页面显示 onPageShow,隐藏调用 onPageHide
组件即将 aboutToAppear,消失调用 aboutToDisappear
资源创建要成对,清理释放不能忘
数据刷新用 PageShow,返回拦截 BackPress
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐