Harmony os——UIAbility 备份恢复:让应用“被系统杀掉”也能无感恢复

47 阅读4分钟

Harmony os——UIAbility 备份恢复:让应用“被系统杀掉”也能无感恢复

这篇是我给自己整理的 「UIAbility 备份恢复」笔记,关键词只有一个—— 避免因为系统回收进程导致用户数据、页面状态白白丢失。


一、什么是 UIAbility 备份恢复?

在 HarmonyOS 里,应用在后台时有可能因为系统资源管控被“回收”(进程退出)。 如果没有做任何处理:

  • 页面栈丢失;
  • 用户输入的临时数据丢失;
  • 下一次再打开应用,又是重新来过。

UIAbility 备份恢复机制的作用:

  • 当 UIAbility 进入后台时,系统会帮你触发一次 备份

  • 当应用被系统回收后,下一次启动时可以自动恢复

    • 页面栈(Navigation 历史)
    • 你在 onSaveState() 里主动保存的数据

这样用户体验会更连贯,像是“从中断处继续”。


二、什么时候会触发 / 不会触发?

不会触发的情况

  • 应用正常关闭

    • 比如用户主动退出应用;
    • 不会触发备份流程。
  • 应用正常启动

    • 比如点击桌面图标、startAbility() 正常启动;
    • 不会触发“恢复流程”,而是正常拉起。

会触发的机制(系统行为)

  • 备份:

    • UIAbility.onBackground() 之后,系统自动调用 onSaveState()

      • 你可以在这里把“临时数据”写入 wantParams
      • 系统会把这些数据序列化后保存到沙箱中。
  • 恢复:

    • 恢复的 Want 数据 会在下次 onCreate() 中传入;
    • 页面栈 会在 onWindowStageCreate() 中由系统恢复;
    • 你可以在 onCreate(want...) 里自己把必要的数据取出来。

三、备份恢复的限制条件(踩坑前必看)

  1. 支持多实例

    • 一个 UIAbility 多实例场景下,每个实例可以单独参与备份恢复。
  2. 备份有效期:7 天

    • 7 天后数据自动失效。
  3. 存储位置

    • 备份数据以文件形式落盘在应用沙箱路径中;
    • 真正对开发者暴露的,是 want.parameters 中的内容。
  4. 大小限制:200 KB

    • 备份数据通过 Want.parameters 序列化;
    • 总大小上限约为 200 KB,所以不适合存大图片、长文本、列表大对象等等。
  5. 重启设备不支持恢复

    • 设备一旦重启,备份恢复流程不会生效;
    • 这个机制更多防的是“系统杀进程”,不是“重启后的无敌恢复”。
  6. UIExtensionAbility 不支持

    • 当前仅支持 UIAbility;
    • UIExtensionAbility 不参与这个备份恢复机制。

四、核心接口:UIAbilityContext.setRestoreEnabled & onSaveState

这些接口都在 UIAbilityContext 上,由 UIAbility 通过 this.context 访问。

接口名说明
setRestoreEnabled(enabled: boolean): void是否启用当前 UIAbility 的备份恢复功能。必须在初始化阶段(onForeground 之前)调用,一般在 onCreate() 调用。
onSaveState(state: AbilityConstant.StateType, wantParams: Record<string, Object>)由系统在 onBackground() 后回调,你在这里往 wantParams 里塞要备份的数据。返回值是 OnSaveResult:比如 ALL_AGREE 表示数据写入正常。

五、开发步骤:从“启用”到“保存 & 恢复”

第一步:在 UIAbility 初始化时开启备份恢复

最简单版本:只开启,不做自定义数据。

 import { UIAbility } from '@kit.AbilityKit';
 ​
 export default class EntryAbility extends UIAbility {
   onCreate() {
     console.info('[Demo] EntryAbility onCreate');
     // 启用当前 UIAbility 的备份恢复能力
     this.context.setRestoreEnabled(true);
   }
 }

第二步:在 onSaveState() 中主动保存数据

常见使用:保存当前表单的临时内容、当前选中的 tab、当前过滤条件等。

 import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
 ​
 export default class EntryAbility extends UIAbility {
   onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
     console.info('[Demo] EntryAbility onCreate');
     this.context.setRestoreEnabled(true);
 ​
     // 应用恢复时可以在 want.parameters 里拿到之前保存的数据
     if (want && want.parameters) {
       const recoveryMyData = want.parameters['myData'];
       console.info(`[Demo] recovery myData: ${JSON.stringify(recoveryMyData)}`);
       // TODO: 根据 recoveryMyData 恢复 UI / 状态
     }
   }
 ​
   onSaveState(
     state: AbilityConstant.StateType,
     wantParams: Record<string, Object>
   ) {
     console.info('[Demo] EntryAbility onSaveState');
     // 将需要恢复的内容写入 wantParams
     // 注意:体积建议控制在 200KB 以内
     wantParams['myData'] = 'my1234567';
 ​
     // 告诉系统:我这次保存没问题,可以使用我写入的数据
     return AbilityConstant.OnSaveResult.ALL_AGREE;
   }
 }

这里可以总结一下用法:

  • onSaveState()

    • 系统调用;
    • 你往 wantParams 塞各种 key-value(会被存起来);
    • 返回 OnSaveResult.ALL_AGREE 表示保存成功。
  • 下一次恢复启动时:

    • onCreate(want...) 被调用;
    • 恢复数据在:want.parameters['myData']
    • 你可以用它恢复 UI 状态、变量值等。

六、实践小建议(以防踩坑)

  1. 只存“轻量级”数据

    • ✅ 存:字符串、小对象、当前页面 ID、筛选条件、草稿内容等;
    • ❌ 不推荐:图片二进制、大数组、完整列表、复杂 DOM 结构等。
  2. 避免强依赖:视为“优化体验”的加分项

    • 备份恢复并不是持久化存储(那是 DB / KVStore 的职责);
    • 可以把它当作“加一层保险”,而不是“唯一的数据来源”。
  3. 注意多实例场景

    • UIAbility 多实例时,每个实例可以独立备份;
    • 标识粒度一般通过系统内部处理,你只需要保证自己在 wantParams 中存的 key 不乱即可。
  4. 记住:重启设备不恢复

    • 如果是必须要跨设备重启存在的数据,请用数据库 / 文件 / KV;

七、一句话总结

UIAbility 备份恢复 = 系统帮你在后台阶段做一次「轻量状态快照」,在下一次冷启动时还原。 你要做的只是:

  1. this.context.setRestoreEnabled(true)
  2. onSaveState() 里往 wantParams 写需要的状态
  3. onCreate(want) 中把 want.parameters 拿出来用