Activity 进程优先级与 onDestroy 可靠性

1. Android 为什么要有进程优先级?

Android 是多任务系统,后台可能有很多 App 进程。

当系统内存不足时,系统会根据进程的重要程度决定优先回收哪些进程。

可以简单理解为:

越靠近用户正在操作的进程,优先级越高;
越远离用户、越没有组件运行的进程,越容易被回收。

2. 常见进程优先级

大致可以理解为:

前台进程 > 可见进程 > 服务进程 > 后台 / 缓存进程 > 空进程
类型 说明
前台进程 正在与用户交互,优先级最高
可见进程 用户能看到,但不一定能交互
服务进程 有正在运行的 Service
后台 / 缓存进程 Activity 不可见,仅保留缓存状态
空进程 没有活跃组件,主要用于缓存

3. 前台进程

前台进程通常是用户正在操作的 Activity 所在进程。

例如:

当前正在显示并交互的页面

这种进程优先级最高,系统一般不会轻易杀死。


4. 可见进程

可见进程指页面仍然可见,但不一定是当前焦点。

例如:

被透明 Activity 覆盖
被 Dialog 样式 Activity 覆盖
分屏中可见但没有焦点

这种进程仍然和用户感知有关,所以优先级高于完全后台进程。


5. 服务进程

如果进程中有正在运行的 Service,优先级会比普通后台 / 缓存进程高。

例如:

音乐播放
文件下载
定位
数据同步

但是要注意:

Service 不能保证进程永远不被杀。

当内存紧张时,Service 所在进程仍然可能被系统回收。


6. 版本差异:Android 8.0 之后后台 Service 限制更多

Android 8.0 / API 26 之后,后台 Service 受到更多限制。

如果是用户可感知的长时间任务,通常应该考虑:

前台服务 Foreground Service
WorkManager
JobScheduler

例如音乐播放、导航、录音、下载这类任务,如果需要长期运行并且用户能感知,应该考虑前台服务,而不是普通后台 Service。


7. 后台 / 缓存进程

当 Activity 执行了:

onStop()

表示页面完全不可见。

这类进程更容易在内存不足时被系统回收。

比如:

用户按 Home 键
用户打开另一个 App
当前页面被其他全屏 Activity 完全覆盖

8. 空进程

空进程没有正在运行的 Activity、Service、Receiver 等组件。

它只是系统为了下次启动更快而保留的缓存进程,优先级最低,最容易被杀。


9. 为什么 onDestroy 不可靠?

onDestroy() 表示 Activity 即将销毁,但不能把它当成可靠的最终通知。

常见触发:

用户按返回键退出 Activity
代码调用 finish()
配置变化导致 Activity 重建

但下面这些情况可能不会正常回调每个 Activity 的 onDestroy()

系统直接杀死进程
厂商系统后台清理
内存极度紧张
用户从最近任务中强制清理

所以不要依赖:

onDestroy() 一定执行

10. 不应该只放在 onDestroy() 的逻辑

不建议只放在 onDestroy() 中:

保存用户重要数据
提交订单状态
保存草稿
上传关键日志
停止关键业务任务
释放必须及时释放的独占资源

如果 onDestroy() 没执行,这些逻辑就可能丢失。


11. 更合理的处理方式

保存用户数据

应该尽早保存:

输入时实时保存
onPause() 保存草稿
业务提交时立即落库

停止 UI 相关任务

可以放在:

onPause()
onStop()

例如:

暂停动画
停止摄像头预览
停止传感器监听
取消 UI 刷新

最终清理

可以放在:

onDestroy()

例如:

解绑 Service
注销 BroadcastReceiver
释放对象引用

但要接受它不是兜底保证。


12. 总结

onPause:适合保存轻量状态
onStop:适合停止不可见页面的资源占用
onDestroy:适合最终清理,但不能依赖它保存关键数据

记忆口诀:

重要数据别等死,onDestroy 不是遗嘱保险箱。

参考来源