从源码角度看Activity生命周期

简介

Activity是几乎所有初级安卓程序员必学的一个知识点。我们都知道安卓最大的特色就是它能够呈现给用户界面,使用户能够与应用程序交互,这其中最重要的基本类就是各个Activity。然而,很多安卓开发者以为自己熟知了Activity的生命周期与launchMode等等知识点,就以为自己理解了它们。然而事实上并不,安卓源码中潜藏着十分复杂的逻辑支撑着Activity生命周期的变化。

本篇文章中,我将以源码的视角,分析Activity的每个生命周期的回调是如何被调用到的。同时,一些安卓framework的基本知识也会详细的讲讲。文章最后会留下几个有意义的问题,很值得我们去理解。

原文在我的博客CheapTalks, 欢迎大家来看看~

整体图

这张图虽然长的很像谷歌官方的那张图,但是的确是我自己画出来了的,和官方的图还是不太一样的。这里面的每个生命周期回调都会在下面的文章中分析到。

onCreate & onStart

启动一个Activity是整个生命周期最复杂的部分,这块老罗的书中就专门用了一章去讲。但我觉着我还是很有必要再用自己的语言去分析一遍,我认为就算看过老罗的那篇关于Activity的文章,再看我写的也是会有不少收获的~

App端调用

ContextImpl.java

  • @Override
  • public void startActivity(Intent intent, Bundle options) {
  • ...
  • // 先获取到Instrumentation实例
  • // Instrumentation实例是在当前进程调用attach后,在bindApplication时初始化的
  • mMainThread.getInstrumentation().execStartActivity(
  • getOuterContext(), mMainThread.getApplicationThread(), null,
  • (Activity) null, intent, -1, options);
  • }

关于ActivityThread的Instrumentation对象初始化,这方面以后我会单独写一篇在进程启动后,应用是如何绑定Application并初始化的分析。进程启动的源码分析,请看我的另一篇博客: 从源码角度看AMS.startProcessLocked

安卓中的双向bind call通信

Instrumentation.java

  • public ActivityResult execStartActivity(
  • Context who, IBinder contextThread, IBinder token, Activity target,
  • Intent intent, int requestCode, Bundle options) {
  • // 获取到ApplicationThread binder call句柄,AMS调用调用它来通知ActivityThread onCreate服务端操作已经完成
  • IApplicationThread whoThread = (IApplicationThread) contextThread;
  • ...
  • try {
  • ...
  • // 获取与AMS binder call 通信的代理对象
  • int result = ActivityManagerNative.getDefault()
  • .startActivity(whoThread, who.getBasePackageName(), intent,
  • intent.resolveTypeIfNeeded(who.getContentResolver()),
  • token, target != null ? target.mEmbeddedID : null,
  • requestCode, 0, null, options);
  • ...
  • } catch (RemoteException e) {
  • throw new RuntimeException("Failure from system", e);
  • }
  • return null;
  • }

安卓AMS核心组件中,最重要的两个binder接口当属IActivityManager和IApplicationThread了,App应用四大组件与AMS服务的双向通信基本仰仗着它们,以下作了个图方便理解:

main binder interface

  • ActivityManagerService继承自ActivityManagerNative, 为所有应用提供组件的服务;所有应用依靠ActivityManagerProxy代理对象调用接口
  • ApplicationThread是ActivityThread中一个内部类,它直接继承了ApplicationThreadNative对象,某种意义上来说是AMS的服务端。当AMS执行完操作时,依靠调用ApplicationThreadProxy的代理对象方法来通知应用完成余下的操作。

这样的设计在安卓系统中很通用,有一点需要额外留意的,大部分App调用到system_server端的接口是非ONEWAY的,也就是同步调用,应用需要等待system_server执行完成。大部分system_server调用到App端的接口是ONEWAY的,也就是异步调用,system_server的服务不需要等待应用完成操作。这样的设计保证了system_server不会收到App处理快慢的影响。

我个人认为,这样的设计其实是有弊端的。例如,如果system_server的某个服务接口调用耗时过久,并且持有了十分紧缺的AMS锁或者说PMS锁,那么其它调用很有可能需要等待这个锁。这样就导致了其它应用的调用等待时间长短会受到系统状况的影响。如果这个应用是前台应用,很有可能会导致ANR,直接影响到用户的使用体验。

因为这块实在是基础,所以谈的比较多。我们继续看Activity.onCreate的调用...

system_server端调用

ActivityManagerService.java

  • @Override
  • public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
  • Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
  • int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
  • ...
  • return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
  • resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
  • profilerInfo, null, null, options, false, userId, null, null);
  • }

ActivityStackSupervisor.java

  • final int startActivityMayWait(IApplicationThread caller, int callingUid,
  • String callingPackage, Intent intent, String resolvedType,
  • IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  • IBinder resultTo, String resultWho, int requestCode, int startFlags,
  • ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
  • Bundle options, boolean ignoreTargetSecurity, int userId,
  • IActivityContainer iContainer, TaskRecord inTask) {
  • ...
  • // 从manifesst中获取Actiivty信息
  • // 这块需要调用到PMS的接口,关于PMS如何读取与解析manifest的中信息,后续会再进行分析
  • ActivityInfo aInfo =
  • resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
  • ...
  • synchronized (mService) {
  • ...
  • int res = startActivityLocked(caller, intent, resolvedType, aInfo,
  • voiceSession, voiceInteractor, resultTo, resultWho,
  • requestCode, callingPid, callingUid, callingPackage,
  • realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
  • componentSpecified, null, container, inTask);
  • ...
  • return res;
  • }
  • }
  • final int startActivityLocked(IApplicationThread caller,
  • Intent intent, String resolvedType, ActivityInfo aInfo,
  • IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  • IBinder resultTo, String resultWho, int requestCode,
  • int callingPid, int callingUid, String callingPackage,
  • int realCallingPid, int realCallingUid, int startFlags, Bundle options,
  • boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
  • ActivityContainer container, TaskRecord inTask) {
  • ...
  • // 创建一个ActivityRecord
  • // AMS中,还存在着BroadcastRecord, ProcessRecord, ServiceRecord这些类,用于表示单个的组件记录
  • ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
  • intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
  • requestCode, componentSpecified, voiceSession != null, this, container, options);
  • ...
  • err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
  • startFlags, true, options, inTask);
  • ...
  • return err;
  • }
  • final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
  • IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
  • boolean doResume, Bundle options, TaskRecord inTask) {
  • ...
  • // 涉及到launchMode的逻辑
  • final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
  • final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
  • final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
  • ...
  • targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
  • ...
  • return ActivityManager.START_SUCCESS;
  • }

这块的代码段其实特别长,涉及到stack的切换,还是挺复杂的。这块以后专门写一篇文章分析Activity launchMode机制。

ActivityStack.java

  • final void startActivityLocked(ActivityRecord r, boolean newTask,
  • boolean doResume, boolean keepCurTransition, Bundle options) {
  • ...
  • task.addActivityToTop(r);
  • task.setFrontOfTask();
  • r.putInHistory();
  • if (!isHomeStack() || numActivities() > 0) {
  • ...
  • mWindowManager.addAppToken(task.mActivities.indexOf(r),
  • r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
  • (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
  • r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
  • ...
  • if (r.mLaunchTaskBehind) {
  • // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
  • // tell WindowManager that r is visible even though it is at the back of the stack.
  • mWindowManager.setAppVisibility(r.appToken, true);
  • ensureActivitiesVisibleLocked(null, 0);
  • } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
  • ...
  • mWindowManager.setAppStartingWindow(
  • r.appToken, r.packageName, r.theme,
  • mService.compatibilityInfoForPackageLocked(
  • r.info.applicationInfo), r.nonLocalizedLabel,
  • r.labelRes, r.icon, r.logo, r.windowFlags,
  • prev != null ? prev.appToken : null, showStartingIcon);
  • r.mStartingWindowShown = true;
  • }
  • } else {
  • // If this is the first activity, don't do any fancy animations,
  • // because there is nothing for it to animate on top of.
  • mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
  • r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
  • (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
  • r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
  • ...
  • }
  • ...
  • if (doResume) {
  • mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
  • }
  • }

以上代码涉及到window apptoken, TaskRecord的操作,详细看的话篇幅很大,先略过...

ActivityStackSupervisor.java

  • boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
  • Bundle targetOptions) {
  • ...
  • if (isFrontStack(targetStack)) {
  • // 将当前ActivityStack置顶
  • result = targetStack.resumeTopActivityLocked(target, targetOptions);
  • }
  • ...
  • return result;
  • }

ActivityStack.java

  • final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
  • ...
  • try {
  • ...
  • result = resumeTopActivityInnerLocked(prev, options);
  • }
  • ...
  • return result;
  • }
  • private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
  • ...
  • // Find the first activity that is not finishing.
  • final ActivityRecord next = topRunningActivityLocked(null);
  • ...
  • final TaskRecord prevTask = prev != null ? prev.task : null;
  • if (next == null) {
  • ...
  • // 这里涉及到回到桌面的逻辑...
  • return isOnHomeDisplay() &&
  • mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
  • }
  • ...
  • ActivityStack lastStack = mStackSupervisor.getLastStack();
  • if (next.app != null && next.app.thread != null) {
  • ...
  • } else {
  • // Whoops, need to restart this activity!
  • if (!next.hasBeenLaunched) {
  • next.hasBeenLaunched = true;
  • } else {
  • ...
  • mStackSupervisor.startSpecificActivityLocked(next, true, true);
  • }
  • ...
  • return true;
  • }

ActivityStackSupervisor.java

  • void startSpecificActivityLocked(ActivityRecord r,
  • boolean andResume, boolean checkConfig) {
  • // Is this activity's application already running?
  • ProcessRecord app = mService.getProcessRecordLocked(r.processName,
  • r.info.applicationInfo.uid, true);
  • ...
  • if (app != null && app.thread != null) {
  • try {
  • ...
  • // 先前的服务端操作已经完成,且应用进程已经存在,开始启动Activity
  • realStartActivityLocked(r, app, andResume, checkConfig);
  • return;
  • } catch (RemoteException e) {
  • ...
  • }
  • // 如果Activity所在进程未启动,则会先创建进程,再启动这个Activity
  • mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
  • "activity", r.intent.getComponent(), false, false, true);
  • }

此处,如果Activity所在进程不存在,则会先创建进程,然后再绑定Application,最后启动这个Activity

  • final boolean realStartActivityLocked(ActivityRecord r,
  • ProcessRecord app, boolean andResume, boolean checkConfig)
  • throws RemoteException {
  • ...
  • // 更新进程的优先级
  • mService.updateLruProcessLocked(app, true, null);
  • mService.updateOomAdjLocked();
  • ...
  • final ActivityStack stack = task.stack;
  • try {
  • ...
  • app.forceProcessStateUpTo(mService.mTopProcessState);
  • // binder call 回到客户端
  • app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
  • System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
  • new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
  • task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
  • newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
  • ...
  • } catch (RemoteException e) {
  • ...
  • }
  • ...
  • return true;
  • }

到这里,Activity的创建在服务端就完成了,现在就是调用到客户端完成Activity的onCreate生命周期调用

ActivityThread.java

  • @Override
  • public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
  • ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
  • CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
  • int procState, Bundle state, PersistableBundle persistentState,
  • List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
  • boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
  • ...
  • sendMessage(H.LAUNCH_ACTIVITY, r);
  • }
  • public void handleMessage(Message msg) {
  • ...
  • case RELAUNCH_ACTIVITY: {
  • Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
  • ActivityClientRecord r = (ActivityClientRecord)msg.obj;
  • handleRelaunchActivity(r);
  • Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  • } break;
  • }
  • private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  • ...å
  • // Initialize before creating the activity
  • WindowManagerGlobal.initialize();
  • Activity a = performLaunchActivity(r, customIntent);
  • ...
  • }

在ActivityThread中,维护着一个名为H的Handler类,它会往主线程的消息队列中抛入事件。当system_server binder call到App端时,App的Binder线程并不会直接去做各种操作,而是向主线程队列中sendMessage,排队等待事件的派发。

```java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 反射创建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
...

  • try {
  • // 获取Application实例
  • Application app = r.packageInfo.makeApplication(false, mInstrumentation);

...
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);

...
activity.mCalled = false;
// 此处调用Activity.onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
// 这里调用Activity.onStart方法
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
// 这里调用Activity.onRestroeInstanceState方法
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
// 调用Activity.onPostCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
...
}
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {

top Created with Sketch.