记一次后台 Activity 被回收的 Case

426 阅读2分钟

本文已参与『新人创作礼』活动,一起开启掘金创作之路。

我在平时的应用开发工作中,我很少考虑到Activity的回收和恢复的问题。当然在面试中这是一个老生常谈的问题。如果你是一个Android开发者,下面两个方法,你肯定熟悉。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
    super.onSaveInstanceState(outState, outPersistentState)
}

上面两个方法涉及到Activity的销毁和重建。我在一个需求上遇到了这个case。这个需求场景是这样的。α Activity被启动之后需要调用moveTaskToBack(true);方法将其回退到后台,同时在近期任务栏中隐藏掉它。但是在实际的联调过程中发现这个Activity的声明周期从onCreate()一直调用到onDestroy(),然后消失了。当时我很费解。这是什么情况。没有显式调用finish()这个Activity竟然没有了。没有办法,晚上只能先哄儿子睡觉了。在哄儿子睡觉的过程中我想到了进程优先级,又想到了Activity的生命周期和优先级。在我的印象中RESUMED状态的Activity优先级肯定是最高的。然后又想到了上面两个方法。我在方法中打印了日志。复现了一下,onSaveInstanceState 果然被调用了。知道了问题的原因自然就想办法解决这个问题。 我想的解决方法是,将这个Activity绑定一个前台服务,通过前台服务提高Activity的优先级,从而避免被回收,结果没有起任何作用,activity还是被回收。后来,想到了在将Activity的launchMode从singleTask改成SingleInstance之前是可以的。我就将launchMode改回成singleTask看一下。修改启动模式之后,发现还是Activity还是有机率被回收。这就说明和启动模式没有关系。又考虑是不是退栈的问题导致的?于是我在调用moveTaskToBack(true);之前和之后分别使用adb shell dumpsys activity activities 命令输出了activity的任务栈情况。发现执行完moveTaskToBack(true);后,Activity会移动到activities的栈底(每个Display包含多个任务栈,这些任务栈会维护在ActivityStack中。按照从顶部到底部进行排序,退栈后的任务栈会在最底部),这个部分知识涉及到AMS,显然我还不是很了解。我猜测系统会在某个时刻回收这个Task,有可能是自动回收。也有可能是某个逻辑触发了这次回收。 这个问题还没有解决。后面解决之后我会再进行更新。