第9章 四大组件的工作过程
所谓四大组件是Activity、Service、BroadcastReceiver、ContentProvider。了解了他们的工作流程,可以更好的理解Android体系结构。
9.1 Activity
我们经常使用Activity#startActivity(intent)方法来启动一个Activity。startActivity()方法有许多重载,但是最后都会调用到startActivityForResult(Intent, int, Bundle)。
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) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
而Activity启动的实际执行是这一句mInstrumentation.execStartActivity(...);
继续跟踪:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
// ……
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), 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;
}
看到这一句:int result = ActivityManager.getService().startActivity(...);
ActivityManager.getService()获取到的是一个实现了IActivityManager接口的Binder(这里跟书中有一些出入,应该是sdk版本的差异,我使用的是api 27,ActivityManagerNative类已经deprecated了),与系统的AMS进行IPC通信。从这里我们可以看出,Activity的启动实际上交给了AMS来进行处理,调用了AMS的startActivity方法,查看这个方法:
@Override
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 startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
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) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
这里开始的流程跟书中就不一样了,启动过程交由ActivityStarter这个类处理,经历startActivityMayWait() -> startActivityLocked() -> startActivity() -> startActivityUnchecked()
在startActivityUnchecked()这个方法中,有这么两句:
mTargetStack.startActivityLocked(mStartActivity, topFocused,
newTask, mKeepCurTransition, mOptions);
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack,
mStartActivity, mOptions);
第一句会将待启动的Activity添加到栈中;第二句会依次调用ActivityStack.resumeTopActivityUncheckedLocked() -> ActivityStack.resumeTopActivityInnerLocked() -> ActivityStackSupervisor.startSpecificActivityLocked()
流程到这里就又跟书上面的一样了。版本的更新修改了一些细节的实现,但是大体的流程还是一样的。
最终,会调用ApplicationThread的scheduleLaunchActivity方法来启动Activity。ApplicationThread是ActivityThread的内部类,它也是一个Binder。scheduleLaunchActivity方法会通过Handler发送消息,调用ActivityThread的handleLaunchActivity方法,这个方法在第四章的时候做了简单的分析,它会调用performLaunchActivity方法。performLaunchActivity主要做了几件事:
- 获取待启动Activity的组件信息;
- 通过Instrumentation创建Activity对象;
- 如果还没有Application对象,那么创建它;
- 创建BaseContext、Window,并和Activity进行绑定attach;
- 调用Activity的onCreate方法。
说实话看到这里,我已经有些模糊了。不如画个流程图来归纳一下。

至此,Activity就已经创建完毕并且启动了。
// TODO 仔细研究一下Instrumentation以及AMS