Android应用被从内存移除时触发ON_CREATE的原因及修复方法
问题根因
观测到的冗余ON_CREATE事件并非系统在清理应用内存时主动发送,是两个实现误区叠加导致的:
- 混淆了
Application.onCreate()生命周期回调和ProcessLifecycleOwner分发的Lifecycle.Event.ON_CREATE事件:前者是应用进程初始化时系统调用的入口回调,后者是ProcessLifecycleOwner用来标记应用进程内首个Activity启动的生命周期事件,二者没有绑定关系。 - Manifest中注册的
com.amazonaws.mobileconnectors.s3.transferutility.TransferService默认是START_STICKY类型服务:滑动最近任务列表杀应用时,系统会先销毁当前栈内所有Activity,再终止应用进程,但START_STICKY类型服务会在进程被杀后尝试自动重启,重启过程会重新初始化Application对象,触发Application.onCreate()里的观察者注册逻辑。此时进程内没有启动任何Activity,ProcessLifecycleOwner初始化后会补发一次ON_CREATE事件,这就是额外回调的来源,和应用被清理的场景无直接关联。 - 不可能在应用被从内存彻底移除时收到
ProcessLifecycleOwner的ON_DESTROY回调:该事件只会在进程内所有生命周期感知组件(Activity、Service)全部永久销毁时分发,系统杀进程回收内存是直接强制终止进程运行,不会走任何组件的正常生命周期回调流程,自然不会触发该事件。
修复方案
从根源消除冗余ON_CREATE事件
- 修正TransferService的启动属性,禁止它在用户手动杀掉应用后自动重启:在Manifest中给该服务增加
android:stopWithTask="true"属性,保证用户划走最近任务时服务随任务栈一起停止,不会触发进程重启。修改后的服务声明如下:<service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService" android:enabled="true" android:stopWithTask="true" /> - 增加进程级注册标记,避免重复注册生命周期观察者:Application类在进程存活期间是全局单例,用一个布尔值标记是否已经注册过ProcessLifecycleObserver,避免进程因服务重启、多进程初始化等场景重复注册导致重复回调,修改后的Application代码如下:
public class ThisApplication extends Application implements LifecycleObserver { private boolean lifecycleObserverRegistered = false; @Override public void onCreate() { super.onCreate(); if (!lifecycleObserverRegistered) { ProcessLifecycleOwner.get().getLifecycle().addObserver(this); lifecycleObserverRegistered = true; } Log.e("ThisApplication", "Inside onCreate()"); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onAppStop() { Log.e("ThisApplication", "ON_STOP()"); } @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onAppStart() { Log.e("ThisApplication", "ON_START()"); } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onAppDestroy() { Log.e("ThisApplication", "ON_DESTROY"); } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onAppResume() { Log.e("ThisApplication", "ON_RESUME"); } @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) public void onAppCreate() { Log.e("ThisApplication", "ON_CREATE"); } }
应用被清理出内存的正确检测方式
不要依赖ON_DESTROY回调检测应用被清理场景,现有稳定实现方案只有两种:
- 检测用户手动划走最近任务:自定义一个服务,重写
onTaskRemoved回调,该方法会在用户从最近任务列表移除应用任务时被系统调用,可在方法内执行清理上报、资源释放逻辑。 - 检测应用被系统低内存回收:该场景无实时回调,可在应用进入后台时写入一个持久化标记位,应用下次冷启动时检查该标记位,如果标记位存在且没有经过正常的
ON_STOP流程清理,就说明上次应用是被系统直接杀进程回收的。
注意:不要将核心业务逻辑绑定在进程被杀的回调上执行,部分深度定制ROM会跳过所有生命周期回调直接杀进程,无法保证逻辑100%执行。
内容的提问来源于stack exchange,提问作者Alyoshak
相关产品推荐
相关产品推荐

