1.1 Activity 生命周期
前言:最近面试了几家公司,包括几家一流的互联网公司,发现一流互联网技术面试与我之前的面试还是有一些差异,他们非常注重对 Android 源码的理解和掌握,而且问的问题也很基础。之前的面试都会问你知道某个东西吗,简述一下如何使用基本就算是合格,而一流的互联网技术面试要求你能够阐述出源码是如何实现的,讲述流程,逻辑等,也希望广大开发者注重对源码的理解和掌握,源码是最优秀的老师,没有之一。
我也把我的面试经历分享给朋友,他们推荐我读一下《Android 开发艺术探索》,我读完后,发现许多面试的问题,这本书都讲到了。下面的系列文章是我对该书的一些知识点做一些笔记。
生命周期相关的几个问题
-
问题1: onStart 和 onResume、onPause 和 onStop 从描述上来看差不多,对我们来说有什么实质的不同呢?
onStart 和 onStop 是从 Activity 是否可见这个角度来回调的,而 onResume 和 onPause 是从 Activity 是否位于前台这个角度来回调的。
-
问题2: 假设当前 Activity 为 A,如果这时用户打开一个新 Activity B,那么 B 的 onResume 和 A 的 onPause 哪个先执行呢?
先执行 A 的 onPause,接下来是 B 的 onCreate,onStart,onResume,再是 A 的 onStop。这一点可以从源码中得出。
简单来说,Activity 的启动会涉及到 ActivityManagerService(下面简称AMS)。AMS 内部维护一个 ActivityStack 并负责栈内的 Activity 的状态同步,AMS 通过 ActivityThread 去同步 Activity 的状态从而完成生命周期方法的调用。在 ActivityStack 中的 resumeTopActivityInnerLocked 方法中,有如下一段代码:/** * If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity to be paused, * while at the same time resuming the new resume activity only if the previous activity can't go into * Pip since we want to give Pip activities a chance to enter Pip before resuming the next activity. */ final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 && !lastResumedCanPip; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, next, false); }
可以看出,新 Activity 启动之前,栈顶的 Activity 需要先 onPause 后,新的 Activity 才能启动。
-
问题3: 资源相关的系统配置发生改变导致 Activity 被杀死并重新创建的生命周期过程,比如 Activity 横竖屏切换。
默认情况下,Activity 横竖屏切换会被销毁并且重新创建,当然我们可以阻止系统重新创建我们的 Activity。onPause、onStop、onDestroy 会被调用,同时由于 Activity 是在异常情况下终止的,系统会调用 onSaveInstanceState 来保存当前 Activity 的状态,调用时机在 onStop 之前,与 onPause 没有关系。Activity 重新创建后,系统会调用 onRestoreInstanceState,把 onSaveInstanceState 方法保存的 Bundle 对象作为参数传递给 onRestoreInstanceState 以及 onCreate 方法。onRestoreInstanceState 在 onStart 之后。
Activity 去调用 onSaveInstanceState 去保存数据,实际是 Activity 去委托 Window 去保存数据,Window 去委托它上面的顶级容器去保存数据。顶层容器是一个 ViewGroup,ViewGroup 再一一通知它的子元素去保存数据,这样整个数据保存过程就完成了。数据恢复过程也是类似的。
这是一种典型的委托思想,上层委托下层、父容器委托子元素去处理一件事情。