说到Activity大家一定很熟悉,下面结合源码简单介绍下其工作过程,这里主要介绍过程,源码只是辅助,如果想了解的很详细,建议大家还是看源码,源码也有注释,绝大部分也能明白。源码分析部分比较长,如果想要快速获取知识可以看最后的总结。文章主要分4部分:四大组件简介、AMS启动ApplicationThread、ApplicationThread启动Activity和总结。总结有时序图及相关的类及调用的方法。
1. 四大组件的简介
Android的四大组件,除了BroadcastReceiver其他的三个必须在AndroidManifest中注册。BroadcastReceiver既可以在AndroidManifest中注册,也可以在代码注册。关于调用方式,Activity、Service、BroadcastReceiver都需要Intent调用,ContentProvider则不需要。
Activity是一种展示的组件,它可以向用户展示一个界面,并接受用户的一些操作,Activity无疑是最重要的一种组件。对于用户来讲,Activity几乎是Android应用的全部,其他的三个组件,用户几乎感知不到。Activity的启动是通过Intent触发的,触发方式分为显式跟隐式。显式Intent可以明确地指向一个Activity组件,隐式Intent则指向一个或多个目标Activity组件,当然也可能没有任何一个Activity组件可以处理这个隐式Intent。Activity还有多种启动模式,这里先不介绍。Activity组件是可以停止的,一般调用finish方法来停止。
Service是一种后台运算的组件,可以在后台执行一系列的操作。Service不能被用户感知,Service组件和Activity组件略有不同,Activity组件只有一种运行模式,即Activity处于启动状态,但是Service组件却有两种状态:启动状态和绑定状态。当Service组件处于启动状态时,这个时候Service内部可以做一些后台计算,并且不需要和外界有直接的交互。尽管Service组件是用于执行后台计算的,但是它本身是运行在主线程中的,因此耗时的后台计算仍然需要在单独的线程中去完成。当Service组件处于绑定状态时,这个时候Service内部同样可以进行后台计算,但是处于这种状态时外界可以很方便地和Service组件进行通信。Service组件也是可以停止的,停止一个Service组件稍显复杂,需要灵活采用stopService和unBindService这两个方法才能完全停止一个Service组件。
BroadcastReceiver是一种消息型组件,用于在不同的组件或者是不同的应用之间传递信息。同样的BroadcastReceiver也不能被用户感知,BroadcastReceiver也叫广播,广播的注册有两种方式:静态注册和动态注册。静态注册是指在AndroidManifest中注册广播,这种广播在应用安装时会被系统解析,此种形式的广播不需要应用启动就可以收到相应的广播。动态注册广播需要通过Context.registerReceiver()来实现,并且在不需要的时候要通过Context.unRegisterReceiver()来解除广播,此种形态的广播必须要应用启动才能注册并接收广播,因为应用不启动就无法注册广播,无法注册广播就无法收到相应的广播。在实际开发中通过Context的一系列send方法来发送广播,被发送的广播会被系统发送给感兴趣的广播接收者,发送和接收过程的匹配是通过广播接收者的<intent-filter>来描述的。可以发现,BroadcastReceiver组件可以用来实现低耦合的观察者模式,观察者和被观察者之间可以没有任何耦合。由于BroadcastReceiver的特性,它不适合用来执行耗时操作。BroadcastReceiver组件一般来说不需要停止,它也没有停止的概念。
ContentProvider是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。和BroadcastReceiver一样,ContentProvider同样无法被用户直接感知。对于一个ContentProvider组件来说,它的内部需要实现增删改查这四种操作,在它的内部维持着一份数据集合,这个数据集合既可以通过数据库来实现,也可以采用其他任何类型来实现,比如List和Map,ContentProvider对数据集合的具体实现并没有任何要求。需要注意的是,ContentProvider内部的insert、delete、update和query方法需要处理好线程同步,因为这几个方法是在Binder线程池中被调用的,另外ContentProvider组件也不需要手动停止。
2. Activity的启动过程:ActivityManagerService启动ApplicationThread
android中的四大组件,进行了很大程度的封装与优化,学习下他们的代码,对大家的水平提升必然有很大的帮助的。下面我们就从源码入手分析下Activity的工作过程。
Intent intent = new Intent();
intent.setClass(context, activityName);
startActivity(intent);
上面的代码是一段启动Activity的代码,很简洁,直接可以启动对应的Activity。作为应用开发者,我们大部分时间并不care Activity到底是怎么启动的,但是如果是ROM开发者,或者是性能调优,复杂问题定位了解Activity的启动就显得非常重要了,闲话莫讲,上源码。
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
startActivity有若干的重载方式,最后我们可以发现如上的代码,最后启动还是调用了startActivityForResult。兜兜转转还是它。PS:上面代码的中else里的startActivityForResult最后也是调用了上面的startActivityForResult
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
还是之前我说的,如果想要了解的清楚,其实看注释比看别人讲解的文章更能得到一手资料。当然,如果是初学者看注释可能还是有些难度的。下面我们还是简单分析一下。
上面代码的mParent是ActivityGroup,就是在一个界面中嵌入多个Activity,显然现在是用Fragment来代替,API13后就被废弃了,所以我们只要看mParent==null部分的逻辑就好。下面说下Instrumentation,额,先说下参数:mMainThread.getApplicationThread(),看名就知道这是一个ApplicationThread,它又是ActivityThread的一个内部类,这为后面的分析埋下了伏笔,一开始就有的东西,很大概率是个关键的点。我们继续看,execStartActivity方法。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
...
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getBasePackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
OK,代码的最后我们发现,最终启动Activity的真身是 ActivityTaskManager.getService()的startActivity方法。这就是传说中的ActivityManagerService,AKA:AMS。我们直接看getService方法。
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
很明显,这是个Binder对象,IActivityManager类型的。上面的Singleton是单例的一个封装类,第一次调用的时候回通过create方法来初始化这个Binder对象。
下面我们先看下Instrumentation.execStartActivity中的checkStartActivityResult方法。
public static void checkStartActivityResult(int res, Object intent) {
if (!ActivityManager.isStartResultFatalError(res)) {
return;
}
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
case ActivityManager.START_PERMISSION_DENIED:
throw new SecurityException("Not allowed to start activity "
+ intent);
...
case ActivityManager.START_CANCELED:
throw new AndroidRuntimeException("Activity could not be started for "
+ intent);
default:
throw new AndroidRuntimeException("Unknown error code "
+ res + " when starting " + intent);
}
}
这么多case,显然, checkStartActivityResult的作用很明显,就是检查启动Activity的结果。当无法正确地启动一个Activity时,这个方法会抛出异常信息。
我们继续分析AMS的startActivity方法。
...
final ActivityStarter mActivityStarter;//声明ActivityStarter
...
public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return this.startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId());
}
//UserHandle.getCallingUserId() 调用者ID
...
public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
//判断是否被隔离
this.enforceNotIsolatedCaller("startActivity");
//检查调用者权限
userId = this.mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, 2, "startActivity", (String)null);
return this.mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, (IVoiceInteractionSession)null, (IVoiceInteractor)null, resultTo, resultWho, requestCode, startFlags, profilerInfo, (WaitResult)null, (Configuration)null, bOptions, false, userId, (IActivityContainer)null, (TaskRecord)null, "startActivityAsUser");
}
从上面的代码我们看到,启动Activity的事又交给了一个ActivityStarter,好吧,我们接着看这个ActivityStarter(代码比较多,这里只给出重点的几行):
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 globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask, String reason) {
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
} else {
...
synchronized(this.mService) {
if (container != null && container.mParentActivity != null && container.mParentActivity.state != ActivityState.RESUMED) {
return -96;
} else {
...
ActivityStack stack;
if (container != null && !container.mStack.isOnHomeDisplay()) {
stack = container.mStack;
} else {
stack = this.mSupervisor.mFocusedStack;
}
stack.mConfigWillChange = globalConfig != null && this.mService.getGlobalConfiguration().diff(globalConfig) != 0;
long origId = Binder.clearCallingIdentity();
int res;
...
//核心赋值
res = this.startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask, reason);
...
this.mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
return res;
}
}
}
}
从上面的代码我们看到,调用了startActivityLocked,其中新增的参数inTask,是TaskRecord类型的,表示Activity所在的栈,reason是Activity启动的理由。上面代码比较简略,startActivityMayWait方法里还有些逻辑处理,用来处理Intent和Flags如何生成一个Activity,并把Activity与Task相关联。我们再来看下startActivityLocked:
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask, String reason) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
} else {
this.mLastStartReason = reason;
this.mLastStartActivityTimeMs = System.currentTimeMillis();
this.mLastStartActivityRecord[0] = null;
this.mLastStartActivityResult = this.startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, this.mLastStartActivityRecord, container, inTask);
if (outActivity != null) {
outActivity[0] = this.mLastStartActivityRecord[0];
}
return this.mLastStartActivityResult != 102 ? this.mLastStartActivityResult : 0;
}
}
里面有关于启动理由的判断,校验失败抛出异常。成功的情况下,又调用了startActivity方法:
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask) {
ProcessRecord callerApp = null;
...
if (caller != null) {
//获取Launcher进程
callerApp = this.mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//获取Launcher进程的pid、uid
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w("ActivityManager", "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString());
err = -94;
}
}
...
//创建将要启动的Activity的描述类ActivityRecord
ActivityRecord r = new ActivityRecord(this.mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, this.mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, this.mSupervisor, container, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
...
this.doPendingActivityLaunchesLocked(false);
return this.startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);
}
上面的代码段可以看出,参数caller是层层嵌套传递的IApplicationThread,指向的是Lanucher所在的应用程序进程的ApplicationThread。参数callerApp是一个ProcessRecord类型的,用来记录一个应用程序进程,同样的,ActivityRecord用来记录Activity相关的信息。最后方法有调用了同名的startActivity:
private int startActivity(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
int result = -96;
try {
this.mService.mWindowManager.deferSurfaceLayout();
result = this.startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity);
} finally {
if (!ActivityManager.isStartResultSuccessful(result) && this.mStartActivity.getTask() != null) {
this.mStartActivity.getTask().removeActivity(this.mStartActivity);
}
this.mService.mWindowManager.continueSurfaceLayout();
}
...
return result;
}
这里其实没有复杂的逻辑,直接调用了startActivityUnchecked方法。
不过大家看有个deferSurfaceLayout()方法,也就是在startActivityUnchecked结果返回后,对应的还有个continueSurfaceLayout()方法,这个是WindowsManagerService的方法。看源码这是一个性能优化的操作,意思是多个变量改变后默认会有多次更新操作,对于比较频繁的更新,性能上考虑可以合并到一起更新。这两个方法就是实现这个功能的。deferSurfaceLayout记录更新次数Depth,continueSurfaceLayout方法首先Depth--,然后判断Depth是否<=0,是就更新,不是不操作。大家可以借鉴作为性能优化的手段:deferSurfaceLayout-->do something-->continueSurfaceLayout。
继续看startActivityUnchecked,这里源码涉及的处理比较多 ,比如设置了Activity启动模式怎么处理的,启动根Activity时怎么处理等,原理介绍直接在代码中注释,不重点的保持了源码的英文注释
:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (mStartActivity.getTask() == null) {
mStartActivity.setTask(reusedActivity.getTask());
}
if (reusedActivity.getTask().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTask().setIntent(mStartActivity);
}
//这部分是要传递一个新的intent,以防后续Activity会被再次使用,这里确保第一次操作就记录下来。
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
final TaskRecord task = reusedActivity.getTask();
//移除Activity Task中目前Activity之上的所有Activity。通常情况是重Task为初始化状态
//这个状态相当于singleTask模式启动activity。
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
//上面的代码是移除Task中的reusedActivity,然后ActivityRecord也会移除相应的TaskRecord
//下面的方法setTargetStackAndMoveToFrontIfNeeded,会用到Task的实例。
if (reusedActivity.getTask() == null) {
reusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
top.getTask().setIntent(mStartActivity);
}
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
// When there is a reused activity and the current result is a trampoline activity,
// set the reused activity as the result.
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
outActivity[0] = reusedActivity;
}
return START_TASK_TO_FRONT;
}
}
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
null /* data */);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
//singleTop模式启动,检查是否需要再次启动
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// 确保准确的重启了顶部的Activity
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
// 开启一个新的Task,对应启动模式singleInstance
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//创建新的Task
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
if (mSourceRecord != null) {
mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
}
if (newTask) {
EventLog.writeEvent(
EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
mStartActivity.getTask().taskId);
}
ActivityStack.logStartActivity(
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
mTargetStack.mLastPausedActivity = null;
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// 如果Activity没有获取焦点,就不要resume它,但是我们任然要保证它启动时变得可见,启动时同时会触发进入动画。典型的例子就是画中画。
// 如果栈内的Activity有遮罩层,也不会resume Activity,
// 作为将要启动的Activity在遮罩层移除之前会保持在可见态暂停的状态。
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// 通知window manager 在当前Activity执行app transition,即切换窗口操作,
// 因前述几行不会执行resume,app transition也就不会被触发。
mWindowManager.executeAppTransition();
} else {
// 如果目标栈之前没有获取焦点(之前栈顶运行的Activity不可见),
//任何移动目标栈到前台的先前的回调,都不会更新已经获取焦点的栈。
//如果开启的新的Activity使栈可以获取焦点,那么需要确保相应的更新已获取焦点的栈。
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
}
在上面代码最后一段注释的地方,resumeFocusedStackTopActivityLocked
方法,代码走到这个分支的话,说明前述状态没有,Activity属于第一次启动。看下源码:
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//获取当前栈顶的ActivityRecord
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {//记录不存在,或者状态不是RESUMED
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
//从MoveTaskToFront操作中去掉所有的留存窗口切换。
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
上面源码可以看出,第一次启动的Activity会执行resumeTopActivityUncheckedLocked
方法。这个方法是ActivityStack中的:
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// 判断递归标记
return false;
}
boolean result = false;
try {
// 避免递归的标记
mStackSupervisor.inResumeTopActivity = true;
//实际执行方法
result = resumeTopActivityInnerLocked(prev, options);
} finally {
// 重置递归的标记
mStackSupervisor.inResumeTopActivity = false;
}
mStackSupervisor.checkReadyForSleepLocked();
return result;
}
上面的源码可以看出,又执行了resumeTopActivityInnerLocked
方法:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// 找到下一个未结束可获取焦点的栈顶Activity resume。
// 如果这个栈顶Activity不可获取焦点,会resume下一个可获取焦点的栈的栈顶元素。
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
mStackSupervisor.cancelInitializingActivities();
// 标记下,将要处理pause/resume的情况
// 确保状态在完成处理后重置
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
...
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
resumeTopActivityInnerLocked方法代码及处理特别多,这里主要给出Activity启动相关的,对于重新启动,前后台切换等复杂场景的处理省略掉了,如果对Activity启动各种情况感兴趣可以看下源码。我继续看startSpecificActivityLocked
方法:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 目标Activity的application是否已经运行了,获取所在应用的应用程序进程。
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//一切正常实际执行的方法,
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// 如果抛出dead object exception ,就会执行application的重启操作
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
上面的方法又调用了realStartActivityLocked
方法:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
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);
...
return true;
}
realStartActivityLocked
方法中有很多关于启动的判断,这里省略掉了,最终启动的任务交给了应用程序进程的IApplicationThread
,其实现是ActivityThread
的内部类ApplicationThread
,这里终于介绍到上面第三段代码块后边分析里提到的ActivityThread。讲到这里,Activity启动过程中的一个重要的环节就讲完了:AMS启动ApplicationThread就讲完了。
3. Activity的启动过程:ApplicationThread启动Activity
接上面第二部分的结尾,我看下ApplicationThread的scheduleLaunchActivity
方法:
...
final H mH = new H();
...
// 使用token来识别activity,不需要把activity自身发送给activity manager(对于 ipc更重要)
@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) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
...
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
scheduleLaunchActivity
方法把启动Activity的必要参数,封装到了ActivityClientRecord
中,向H类发送了LAUNCH_ACTIVITY的消息,H类看源码,继承自Handler,最终调用了如下方法:
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
最终消息的处理是由H类完成的:
private class H extends Handler {
...
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;
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;
case PAUSE_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != 0, args.argi2,
(args.argi1 & DONT_REPORT) != 0, args.argi3);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
...
}
上面LAUNCH_ACTIVITY情况下,Message的obj转换成了ActivityClientRecord,getPackageInfoNoCheck
方法返回加载的apk,应用程序进程启动Activity时会加载所需的apk。LAUNCH_ACTIVITY最后调用了ActivityThread中的handleLaunchActivity
方法:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
// 如果进入后台后准备GC,重新激活后忽略GC.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
...
//创建Activity前初始化
WindowManagerGlobal.initialize();
//启动Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//Activity状态标记为Resume
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
// the first time they run, before their window is displayed), and then pausing it.
// However, in this case we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just retain the current
// state it has.
//AMS实际上会从Pause开始启动Activity,因为需要使Activity可见,但是他又不在前台。
//这里的实现是通过一般的启动方式启动(Activity在相应的window展示出来前,第一次启动需要通过onResume()方法),然后暂停。
//在这种情况下,其实不需要一个完整的pause周期,因为AMS假设Activity只是保持了当前的状态
performPauseActivityIfNeeded(r, reason);
//这里需要保持之前的状态,以便再次创建。
// pre-Honeycomb应用的特殊处理
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
//任何异常原因通过AMS停止启动。
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
继续看下启动activity的方法performLaunchActivity
:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
//获取ActivityInfo
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//获取APK描述类LoadedApk
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//获取Activity的ComponentName信息
ComponentName component = r.intent.getComponent();
...
//创建Activity上下文
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
//创建类加载器,并创建Activity实例。
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
//创建Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
...
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
...
appContext.setOuterContext(activity);
//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, window, r.configCallback);
...
//接入网络操作
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
//主题
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
r.activity = activity;
r.stopped = true;
//各种判断
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
...
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
Activity初始化的attach
方法中会创建PhoneWIndow并与当前Activity关联(当然还有很多其他的界面出初始化的操作等):
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
}
继续看ActivityThread的performLaunchActivity
方法,启动Activity还是通过callActivityOnCreate
方法,这是Instrumentation
中的方法:
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
这里调用了Activity的performCreate
方法:
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
performCreate
方法最后调用了Activity的onCreate
方法。这时Activity就启动了。
4总结
这里介绍Activity的启动过程其实省略了一步,就是App第一次是如何启动Activity的。上面写的调用方法其实已经启动了一个Activity了。我们知道启动一个应用其实是从Launcher进程中启动了应用的根Activity,也就是入口的Activity。而启动根Activity也是由AMS来完成的,其步骤跟2、3部分完全一样。但是第一次启动应用还有不一样的地方就是需要创建应用程序进程,而创建应用程序进程又是由Zygote进程来完成的。
4.1根Activity启动过程:
4.2AMS调用ApplicationThread具体过程:
4.3ApplicationThread启动Activity的具体过程:
这里省略了Launcher到AMS启动根Activity的过程,其实很简单,就是通过Launcher调用了activity的
startActivity
方法。
如有错误的地方欢迎大家指正并发表自己的观点。