3-6.【Ability】Ability 被系统回收的条件是什么?如何模拟被系统回收?如何做状态持久化恢复?

3 阅读3分钟

在 HarmonyOS 的 Stage 模型中,系统回收(Termination by System) 是资源调度的核心机制。系统为了保障前台应用的流畅度,会根据优先级动态“修剪”后台的 UIAbility 实例。


1. Ability 被系统回收的条件

系统不会无缘无故回收你的应用,通常遵循以下 “资源优先级法则”

  1. 内存阈值(Memory Pressure): 当系统剩余内存低于预设的安全水位(Watermark)时,回收机制触发。

  2. 优先级排序:

    • 前台(Foreground): 绝对不回收。
    • 可见非焦点(Visible but Unfocused): 如分屏模式下的非活动窗口,优先级高,极少回收。
    • 后台(Background): 优先级最低。系统会按照 LRU(最近最少使用) 算法,优先回收开启时间最早、占用内存最大的后台 Ability。
  3. 托管任务状态: 如果 Ability 关联了后台长连接、音乐播放或定位服务(Continuous Task),其回收优先级会被显著降低(即更难被回收)。


2. 如何模拟被系统回收?

在开发调试阶段,由于手机内存通常很大,很难靠自然等待来触发回收。你可以通过以下两种方式手动触发:

方法 A:利用 DevEco Studio 的调试工具(推荐)

Log 窗口或者 Profiler 工具栏中,有一个 "Terminate Process" 或类似强杀按钮。

  • 模拟步骤: 先将应用按 Home 键切入后台,然后在 IDE 中断开连接或点击停止,模拟进程消失。

方法 B:命令行模拟 (Shell)

通过 hdc 工具向设备发送指令,强制清理内存:

Bash

# 这种方式更接近系统回收,会直接杀掉进程
hdc shell kill -9 [进程PID]

方法 B:设置“不保留活动”(开发者选项)

在 HarmonyOS 设备的 设置 > 系统和更新 > 开发人员选项 中,开启 “不保留活动” (Don't keep activities)

  • 效果: 只要应用一离开前台,系统会立即触发销毁流程,这是测试状态恢复的最佳利器。

3. 如何做状态持久化与恢复?

为了应对“进程消失”带来的数据丢失,ArkTS 提供了 onSaveState 这一关键钩子。

第一步:在回收前保存状态

当 Ability 准备转入后台时,系统会触发 onSaveState。你可以将需要恢复的小型数据存入 want 参数中。

TypeScript

import UIAbility from '@ohos.app.ability.UIAbility';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import Want from '@ohos.app.ability.Want';

export default class EntryAbility extends UIAbility {
  // 1. 系统准备回收前调用
  onSaveState(reason: AbilityConstant.StateType, wantParam: Want): AbilityConstant.OnSaveResult {
    // 将需要恢复的数据存入 wantParam 的 parameters 中
    wantParam.parameters = {
      'input_text': '用户写了一半的评论',
      'scroll_pos': 120
    };
    return AbilityConstant.OnSaveResult.ALL_AGREE;
  }
}

第二步:在重建时恢复数据

当用户从历史任务栈切回应用时,系统会执行冷启动流程。此时 onCreate 的第一个参数 want 中会包含你之前保存的数据。

TypeScript

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
    // 2. 检查是否有恢复数据
    if (launchParam.launchReason === AbilityConstant.LaunchReason.LAST_EXIT_ABNORMAL) {
       let savedText = want.parameters?.['input_text'];
       let scrollPos = want.parameters?.['scroll_pos'];
       // 将数据存入 AppStorage 或传给页面
       AppStorage.setOrCreate('RestoredText', savedText);
    }
  }
}

4. 状态恢复的“黄金法则”

  • 数据量限制: onSaveState 里的 want 适合存轻量级数据(如 ID、位置、简单的表单内容)。
  • 大文件处理: 视频缓存、大量图片数据不要往 want 里塞,应在 onBackground 阶段直接写入磁盘文件或数据库。
  • UI 自动恢复: 对于 TextInput 等基础组件,ArkUI 框架在一定程度上支持自动状态恢复,但复杂的自定义状态(如当前选中的 Tab 索引)必须通过上述代码手动处理。

一句话总结:onSaveState 存变量,靠 PersistentStorageRDB 数据库存重数据,靠 onCreate 判断启动原因来回填。