概述
Activity 作为 Android 的四大组件之一, Android 主要的界面组成部分, 用于直接跟用户进行交互操作, 在面试中与 Activity 相关的知识也是经常被问到, 如果你面试的高级岗位, 那么对 Activity 的启动和绘制流程就必须的熟悉, 本文将从 Activity 的启动流程来分析 Activity. 启动 Activity 的方式大致有两种: 一种是在桌面点击应用程序的图标, 进入应用程序的主界面; 另一种是在应用程序中, 进入一个新的 Activity. 前者属于 launcher 启动的范畴, 本文不做具体的深入分析, 后面会具体的分析, 不过它的实质是从一个应用的 Activity 进入另一个应用 Activity.
因此, 不管是从桌面进入应用主界面, 还是在应用里进入一个新的 Activity, 最终都会调用 Activity$startActivity 方法.
值得注意的是, Android 5.0,7.0 等版本中启动 Activity 的流程略微有一些细小的改变, 但这并不妨碍我们理解 Activity 的启动流程.
Binder 机制
首先, 我们要介绍下 Android 系统中一个重要的内容: Binder 机制. 为了满足进程间的通信, Android 系统将进程分为了用户 (Zygote) 进程和系统 (SystemServer) 进程以及各种应用进程等, 为了能够实现各种进程之间的通讯, Android 系统采用了自己的进程间通讯方式 Binder 机制. 其中主要涉及到了四种角色: Binder Client,Binder Server,Binder Manager, Binder driver. 各种角色之间的关系可以参考下面这张图的介绍:
关于 Binder 机制的具体内容, 可以参考 Android Binder 跨进程通信原理一文.
启动 Activity 流程解读
当我们使用 startActivity() 启动另一个 Activity 后, 主要会调用以下的一些函数.
MyActivity.startActivity()
Activity.startActivity()
Activity.startActivityForResult
Instrumentation.execStartActivty
ActivityManagerNative.getDefault().startActivityAsUser()
首先, 我们来看一下 startActivity() 函数的源码:
- @Override
- public void startActivity(Intent intent) {
- this.startActivity(intent, null);
- }
- @Override
- public void startActivity(Intent intent, @Nullable Bundle options) {
- if (options != null) {
- startActivityForResult(intent, -1, options);
- } else {
- startActivityForResult(intent, -1);
- }
- }
其实, startActivity 还有几个其他重载的方法, 但是最终都会执行到 Activity$startActivityForResult 方法. 如果是调用 startActivity(intent) 启动 Activity, 那么 requestCode 参数则传入 - 1, 表示需要返回 Activity 的数据.
到此继续往下看, startActivityForResult 方法的具体实现如下:
- public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
- @Nullable Bundle options) {
- if (mParent == null) {
- 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 进行了一个判 Null 操作, 可以发现由于我们是第一次启动 Activity, 所以这里的 mParent 为空, 所以会执行 if 分之, 然后调用 mInstrumentation.execStartActivity 方法, 并且这里需要注意的是, 有一个判断逻辑. 即:
- if (requestCode>= 0) {
- mStartedActivity = true;
- }
前面说过, 调用 startActivityForResult 的时候只有 requestCode 的值大于等于 0,onActivityResult 才会被回调.
Instrumentation
然后我们看一下 mInstrumentation.execStartActivity 方法的具体实现. 在看 execStartActivity 方法之前, 首先看一下 Instrumentation,Instrumentation 是 android 系统中启动 Activity 的一个实际操作类, 也就是说 Activity 在应用进程端的启动实际上就是 Instrumentation 执行的. 那为什么是这样呢? 实际上 acitivty 的启动分为应用进程端的启动和 SystemServer 服务进程端的启动的, 多个应用进程相互配合最终完成了 Activity 在系统中的启动的, 而在应用进程端的启动实际的操作类就是 Intrumentation 来执行的.
为了方便理解, 我们直接看 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);
- }
- if (mActivityMonitors != null) {
- synchronized (mSync) {
- final int N = mActivityMonitors.size();
- for (int i=0; i<N; i++) {
- final ActivityMonitor am = mActivityMonitors.get(i);
- ActivityResult result = null;
- if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intent);
- }
- if (result != null) {
- am.mHits++;
- return result;
- } else if (am.match(who, null, intent)) {
- am.mHits++;
- if (am.isBlocking()) {
- return requestCode>= 0 ? am.getResult() : null;
- }
- break;
- }
- }
- }
- }
- 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;
- }
如上, execStartActivity 主要有以下几个参数:
this, 为启动 Activity 的对象;
contextThread, 为 Binder 对象, 是主进程的 context 对象;
token, 也是一个 Binder 对象, 指向了服务端一个 ActivityRecord 对象;
target, 为启动的 Activity;
intent, 启动的 Intent 对象;
requestCode, 请求码;
options, 参数;
通过, execStartActivity 方法可以发现, 该方法主要调用 ActivityManager.getService() 方法, 继续查看 ActivityManager$getService 源码.
- /**
- * @hide
- */
- 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;
- }
- };
- //...code
- }
可以发现, IActivityManager.Stub.asInterface(b), 那么继续看 asInterface 方法的实现:
- static public IActivityManager asInterface(IBinder obj) {
- if (obj == null) {
- return null;
- }
- IActivityManager in =
- (IActivityManager)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
- return new ActivityManagerProxy(obj);
- }
asInterface() 返回一个 ActivityManagerProxy 对象, ActivityManagerProxy 继承与 IActivityManager, 到了这里就引出了我们 android 系统中很重要的一个概念: Binder 机制.
IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)
如上, 是获取一个关联了系统服务 ActivityManagerService 的 Binder 对象. 所以, IBinder 最终和 ActivityManagerService 形成了绑定关系.
- public class ActivityManagerService extends IActivityManager.Stub
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- }
所以, ActivityManager.getService().startActivity(...) 的最终调用的是 ActivityManagerService 的 startActivity 方法.
ActivityManagerService 启动 Activity
首先来看一下, ActivityManagerService$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());
- }
ActivityManagerService 启动 Activity 主要会涉及到以下的一些方法.
ActivityManagerService.startActivity()
ActvityiManagerService.startActivityAsUser()
ActivityStackSupervisor.startActivityMayWait()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.startActivityUncheckedLocked()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.resumeTopActivitiesLocked()
ActivityStackSupervisor.resumeTopActivityInnerLocked()
当 ActivityManagerService 调用 startActivity 方法后, 该方法调用的是 startActivityAsUser(), 该方法的源码如下:
- @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, null,
- "startActivityAsUser");
- }
可以看到这里只是进行了一些关于 userid 的逻辑判断, 然后就调用 mStackSupervisor.startActivityMayWait 方法, 该方法涉及的源码比较多, 下面截取一些核心的代码实现:
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) {
- ...
- 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;
- }
该方法在启动 Activity 后执行了一些逻辑判断后, 最终调用 startActivityLocked 方法.
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) {
- int err = ActivityManager.START_SUCCESS;
- ...
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
- ...
- return err;
- }
这个方法中主要构造了 ActivityManagerService 端的 Activity 对象 ->ActivityRecord, 并在执行了一些逻辑判断后调用了 startActivityUncheckedLocked 方法.
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
- ...
- ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
- targetStack.mLastPausedActivity = null;
- targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
- if (!launchTaskBehind) {
- // Don't set focus on an activity that's going to the back.
- mService.setFocusedActivityLocked(r, "startedActivity");
- }
- return ActivityManager.START_SUCCESS;
- }
startActivityUncheckedLocked 方法中只要执行了不同启动模式不同栈的处理, 并最后调用了 startActivityLocked 的重载方法.
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
- ...
- if (doResume) {
- mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
- }
- }
而这个 startActivityLocked 方法主要执行初始化了 windowManager 服务, 然后调用 resumeTopActivitiesLocked 方法.
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
- Bundle targetOptions) {
- if (targetStack == null) {
- targetStack = mFocusedStack;
- }
- // Do targetStack first.
- boolean result = false;
- if (isFrontStack(targetStack)) {
- result = targetStack.resumeTopActivityLocked(target, targetOptions);
- }
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx>= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx>= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
- if (stack == targetStack) {
- // Already started above.
- continue;
- }
- if (isFrontStack(stack)) {
- stack.resumeTopActivityLocked(null);
- }
- }
- }
- return result;
- }
该函数最终又调用了 resumeTopActivityLocked 方法,
- final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
- if (mStackSupervisor.inResumeTopActivity) {
- // Don't even start recursing.
- return false;
- }
- boolean result = false;
- try {
- // Protect against recursion.
- mStackSupervisor.inResumeTopActivity = true;
- if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
- mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
- mService.updateSleepIfNeededLocked();
- }
- result = resumeTopActivityInnerLocked(prev, options);
- } finally {
- mStackSupervisor.inResumeTopActivity = false;
- }
- return result;
- }
- ApplicationThread
前面说过, ApplicationThread 是 ActivityThread 的内部类, 因此 ApplicationThread 可以调用外部类 ActivityThread 的方法, 启动 Activity 的操作交给了 ActivityThread 来处理. 那么首先来看一下 ApplicationThread$scheduleLaunchActivity 的源码实现.
- @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;
- r.activityInfo = info;
- r.compatInfo = compatInfo;
- r.state = state;
- r.persistentState = persistentState;
- r.pendingResults = pendingResults;
- r.pendingIntents = pendingNewIntents;
- r.startsNotResumed = notResumed;
- r.isForward = isForward;
- r.profilerInfo = profilerInfo;
- r.overrideConfig = overrideConfig;
- updatePendingConfiguration(curConfig);
- sendMessage(H.LAUNCH_ACTIVITY, r);
- }
上面代码最终调用了 ActivityThread$sendMessage 函数, 该部分代码如下:
- 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);
- }
上面使用了 Handler 机制, 来看一下 H$handleMessage 源码.
- private class H extends Handler {
- //...code
- 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;
- //...code
- }
当接受到消息后, 最终调用 ActivityThread$handleLaunchActivity 方法启动 Activity.
- private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
- //...
- Activity a = performLaunchActivity(r, customIntent);
- //...
- if (a != null) {
- //...
- handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
- //...
- } else {
- // If there was an error, for any reason, tell the activity manager to stop us.
- try {
- ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
- }
也就是 performLaunchActivity, 到此我相信大部分的同学都可以看得懂了
来源: https://blog.csdn.net/xiangzhihong8/article/details/79972377