Harmony os——UIAbility 备份恢复:让应用“被系统杀掉”也能无感恢复
这篇是我给自己整理的 「UIAbility 备份恢复」笔记,关键词只有一个—— 避免因为系统回收进程导致用户数据、页面状态白白丢失。
一、什么是 UIAbility 备份恢复?
在 HarmonyOS 里,应用在后台时有可能因为系统资源管控被“回收”(进程退出)。 如果没有做任何处理:
- 页面栈丢失;
- 用户输入的临时数据丢失;
- 下一次再打开应用,又是重新来过。
UIAbility 备份恢复机制的作用:
-
当 UIAbility 进入后台时,系统会帮你触发一次 备份;
-
当应用被系统回收后,下一次启动时可以自动恢复:
- 页面栈(Navigation 历史)
- 你在
onSaveState()里主动保存的数据
这样用户体验会更连贯,像是“从中断处继续”。
二、什么时候会触发 / 不会触发?
不会触发的情况
-
应用正常关闭
- 比如用户主动退出应用;
- 不会触发备份流程。
-
应用正常启动
- 比如点击桌面图标、
startAbility()正常启动; - 不会触发“恢复流程”,而是正常拉起。
- 比如点击桌面图标、
会触发的机制(系统行为)
-
备份:
-
在
UIAbility.onBackground()之后,系统自动调用onSaveState():- 你可以在这里把“临时数据”写入
wantParams; - 系统会把这些数据序列化后保存到沙箱中。
- 你可以在这里把“临时数据”写入
-
-
恢复:
- 恢复的 Want 数据 会在下次
onCreate()中传入; - 页面栈 会在
onWindowStageCreate()中由系统恢复; - 你可以在
onCreate(want...)里自己把必要的数据取出来。
- 恢复的 Want 数据 会在下次
三、备份恢复的限制条件(踩坑前必看)
-
支持多实例
- 一个 UIAbility 多实例场景下,每个实例可以单独参与备份恢复。
-
备份有效期:7 天
- 7 天后数据自动失效。
-
存储位置
- 备份数据以文件形式落盘在应用沙箱路径中;
- 真正对开发者暴露的,是
want.parameters中的内容。
-
大小限制:200 KB
- 备份数据通过
Want.parameters序列化; - 总大小上限约为 200 KB,所以不适合存大图片、长文本、列表大对象等等。
- 备份数据通过
-
重启设备不支持恢复
- 设备一旦重启,备份恢复流程不会生效;
- 这个机制更多防的是“系统杀进程”,不是“重启后的无敌恢复”。
-
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 状态、变量值等。
六、实践小建议(以防踩坑)
-
只存“轻量级”数据
- ✅ 存:字符串、小对象、当前页面 ID、筛选条件、草稿内容等;
- ❌ 不推荐:图片二进制、大数组、完整列表、复杂 DOM 结构等。
-
避免强依赖:视为“优化体验”的加分项
- 备份恢复并不是持久化存储(那是 DB / KVStore 的职责);
- 可以把它当作“加一层保险”,而不是“唯一的数据来源”。
-
注意多实例场景
- UIAbility 多实例时,每个实例可以独立备份;
- 标识粒度一般通过系统内部处理,你只需要保证自己在
wantParams中存的 key 不乱即可。
-
记住:重启设备不恢复
- 如果是必须要跨设备重启存在的数据,请用数据库 / 文件 / KV;
七、一句话总结
UIAbility 备份恢复 = 系统帮你在后台阶段做一次「轻量状态快照」,在下一次冷启动时还原。 你要做的只是:
this.context.setRestoreEnabled(true)- 在
onSaveState()里往wantParams写需要的状态- 在
onCreate(want)中把want.parameters拿出来用