一:正常情况下,activity会经历如下生命周期。
1):onCreate:表示activity正在被创建。
2):onRestart:表示activity正在重新启动。
3):onStart:表示activity正在重新启动。
4):onResume:表示activity已经可见了,已经出现在前台并开始活动。
5):onPause:表示activity正在被停止。
6):onStop:表示activity即将被停止。
7):onDestory:表示activity即将销毁。
当一个特定的activity第一次被创建的时候生命周期如下:
问题1:onStart和onResume、onPause和onStop从描述上来看差不多,本质有什么不同。
onStart和onStop是从Activity是否可见的角度来回调。
onResume和onPause是从是否位于前台来回调
除了这两种区别在实际中没有其他明显区别。
当跳转到其他的activity生命周期如下:activity1先调用onPause 然后activity2创建 然后activity1在onStop;
当再返回activity1的时候生命周期如下:activity1调用onRestart然后onstart-onResume activity2停止然后销毁
当按HOME键返回桌面再点进来。
问题2:当跳转的时候旧activity必须onPause之后才能开启新的activity,为什么?
从Activity启动过程来看,启动Activity的请求会有Instrumentation来处理,然后他们通过Binder像AMS(ActivityManagerService)发请求,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才能启动。最终在ActivityStackSupervisor中的realStartActivityLocked方法会调用如下代码:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
app是ProcessRecord app ,ProcessRecord 中的thread是IApplicationThread thread,所以app.thread的类型是IApplicationThread,而IApplicationThread的具体实现是ActivityThread中的ApplicationThread,所以这段代码最终调用带了ActivityThread中,即ApplicationThread中的scheduleLaunchActivity方法,而scheduleLaunchActivity方法最终会完成Activity的onCreate、onStart、onResume的调用过程,因此可以得出结论是旧Activity先拍、onPause,然后新的Activity再启动。
scheduleLaunchActivity方法中调用了sendMessage(H.LAUNCH_ACTIVITY, r);方法,然后再
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
...
调用了handleLaunchActivity方法,开始执行新Activity的创建流程
二:异常情况下activity生命周期。
当activity被异常回收:
销毁前会调用onSaveInstanceState
重新创建以后会调用onRestoreInstanceState
当系统配置变化后,其onPause、onStop、onDestory都会调用onSaveInstanceState的调用是在onStop之前,用来保存当前Activity状态,和onPause没有既定的时序关系,这个方法只会出现在Activity被异常终止的情况下,正常情况下不会出回调这个方法,当Activity重建后,系统会调用onRestoreInstanceState,并且把Activity销毁时保存的bundle对象当做参数传递给onRestoreInstanceState和onCreate方法,我们可以通过取出保存的数据恢复,从时序上来说onRestoreInstance在onStart之后。
关于保存和恢复view的层次结构,系统流程是这样的:首先Activity意外被终止,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托window去保存数据,window再委托它上面的顶级容器去保存数据,顶层容器是一个ViewGroup,一般情况很可能是DecorView,最后顶层容器再去一一通知子元素保存数据,这样整个数据就保存完成了,这是一种典型的委托思想,上层委托下层。
三:activity优先级
(1)前台可见正在和用户交互的activity优先级最高;
(2)可见但是非前台activity,如activity弹出个窗口。
(3)后台已经暂停的activity优先级最低,当内存不足的时候优先回收这些activity所在的进程,后通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数据。
如果一个进程没有四大组件支持很容易被杀死,比较好的方法是将后台程序放入service中保证优先级的提高,这样就不会轻易被杀死。
如果不想Activity被重建就可以给configChanges属性添加orientation这个值。