今天我们来分析下 Activity 的启动流程, 看看 Activity 是啥时候创建的, 窗口是啥时候创建的, Context 呢?
我们启动一个 Activity 时一般是这样的:
- Intent intent = new Intent(MainActivity.this, TestActivity.class);
- startActivity(intent);
实际上 startActivity 调用的是 Activity 类里面的方法, 在 Activity 类中 startActivity 有多个重载方法, 但最后调用的都是 startActivityForResult 方法
- public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
- @Nullable Bundle options) {
- //mParent 代表的是 ActivityGroup, 肯定是 null 的
- 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);
- // TODO Consider clearing/flushing other event sources and events for child windows.
- } else {
- if (options != null) {
- mParent.startActivityFromChild(this, intent, requestCode, options);
- } else {
- mParent.startActivityFromChild(this, intent, requestCode);
- }
- }
- }
看上面的源码, 这里需要注意的是这里会走 mParent==null 这个分支. mParent 代表的是 ActivityGroup, 也就是一个 Activity 里面再嵌套 Activity, 这种方式已经被 Fragment 替代了.
这里的 mMainThread 就是 ActivityThread, 而 mMainThread.getApplicationThread() 就是 ActivityThread 的内部类 ApplicationThread.ActivityThread 和 ApplicationThread 在 Activity 的启动过程中发挥了很重要的作用.
- //Instrumentation.class
- public ActivityResult execStartActivity(
- Context who, IBinder contextThread, IBinder token, Activity target,
- Intent intent, int requestCode, Bundle options) {
- // 这里可以看到 ApplicationThread 其实是个 Binder
- IApplicationThread whoThread = (IApplicationThread) contextThread;
- Uri referrer = target != null ? target.onProvideReferrer() : null;
- if (referrer != null) {
- intent.putExtra(Intent.EXTRA_REFERRER, referrer);
- }
- ...
- try {
- intent.migrateExtraStreamToClipData();
- intent.prepareToLeaveProcess(who);
- // 调用 ActivityManagerNative 的 getDefault 方法返回 ActivityManagerService
- int result = ActivityManagerNative.getDefault()
- .startActivity(whoThread, who.getBasePackageName(), intent,
- intent.resolveTypeIfNeeded(who.getContentResolver()),
- token, target != null ? target.mEmbeddedID : null,
- requestCode, 0, null, options);
- // 这个方法用于检查 Activity 的启动结果, 如果启动失败是抛出相应的异常
- checkStartActivityResult(result, intent);
- } catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
- }
- return null;
- }
从 Instrumentation 的 execStartActivity 源码可以看到, ApplicationThread 其实是个 Binder, 它主要是供后面从 ActivityManagerService 的进程回调到应用的进程. 同时启动 Activity 的过程通过 Binder 机制转到了 ActivityManagerService.
ActivityManagerService 中的 Activity 的启动过程就相对复杂很多, 需要经过很多的跳转和处理, 比如需要判断要启动的 Activity 的任务栈是否存在, 不存在的话要创建任务栈; 暂停当前的 Activity, 以便当前待启动的 Activity 可以获取焦点等. 这里我们就不跟进去看源码了, 容易绕晕.
ActivityManagerService 做好自己的事儿以后, 就会调用我们传过去的 Binder 对象 ApplicationThread 的 scheduleLaunchActivity 来将进程切换到当前应用的进程, 以便继续完成启动 Activity 的任务.
- //ApplicationThread.class
- @Override
- public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ...) {
- 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;
- ...
- sendMessage(H.LAUNCH_ACTIVITY, r);
- }
ActivityClientRecord 中保存了要启动的 Activity 的信息. 由于 ApplicationThread 是一个 Binder, 所以 scheduleLaunchActivity 是运行在 Binder 线程池中的, 需要通过 Handler 将线程切换到 ActivityThread 的线程中去. 而上面源码中的 H 就是 ActivityThread 中的 Handler.
- private class H extends Handler {
- public static final int LAUNCH_ACTIVITY = 100;
- public static final int PAUSE_ACTIVITY = 101;
- public static final int STOP_ACTIVITY_SHOW = 103;
- public static final int STOP_ACTIVITY_HIDE = 104;
- public static final int RECEIVER = 113;
- public static final int CREATE_SERVICE = 114;
- public static final int SERVICE_ARGS = 115;
- public static final int STOP_SERVICE = 116;
- ...
- String codeToString(int code) {
- if (DEBUG_MESSAGES) {
- switch (code) {
- case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
- case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
- case RECEIVER: return "RECEIVER";
- case CREATE_SERVICE: return "CREATE_SERVICE";
- case SERVICE_ARGS: return "SERVICE_ARGS";
- case STOP_SERVICE: return "STOP_SERVICE";
- ...
- }
- }
- return Integer.toString(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;
- ...
- }
可以看到这个 Handler 里面大量的跟四大组件有关的方法, 其他的组件的一些启动停止等都会回调到这里, 由这个 Handler 处理.
我们看到 Handler H 对 LAUNCH_ACTIVITY 的处理是通过 ActivityThread 的 handleLaunchActivity 方法
- //ActivityThread.class
- private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
- ...
- Activity a = performLaunchActivity(r, customIntent);
- if (a != null) {
- r.createdConfig = new Configuration(mConfiguration);
- reportSizeConfigurations(r);
- Bundle oldState = r.state;
- handleResumeActivity(r.token, false, r.isForward,
- !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
- if (!r.activity.mFinished && r.startsNotResumed) {
- performPauseActivityIfNeeded(r, reason);
- if (r.isPreHoneycomb()) {
- r.state = oldState;
- }
- }
- } else {
- try {
- ActivityManagerNative.getDefault()
- .finishActivity(r.token, Activity.RESULT_CANCELED, null,
- Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
- }
从源码中我们可以看到启动 Activity 的过程最后由 performLaunchActivity 来完成, 完成以后就会调用 handleResumeActivity 方法来调用启动的 Activity 的 onResume 方法.
performLaunchActivity 主要完成了以下几件事:
(1) 从 ActivityClientRecord 中获取待启动的 Activity 组件的信息
- ActivityInfo aInfo = r.activityInfo;
- if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
- Context.CONTEXT_INCLUDE_CODE);
- }
- ComponentName component = r.intent.getComponent();
- if (component == null) {
- component = r.intent.resolveActivity(
- mInitialApplication.getPackageManager());
- r.intent.setComponent(component);
- }
- if (r.activityInfo.targetActivity != null) {
- component = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.targetActivity);
- }
(2) 通过 Instrumentation 类的 newActivity 方法, 利用类加载器来创建 Activity
- Activity activity = null;
- try {
- java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
- activity = mInstrumentation.newActivity(
- cl, component.getClassName(), r.intent);
- StrictMode.incrementExpectedActivityCount(activity.getClass());
- r.intent.setExtrasClassLoader(cl);
- r.intent.prepareToEnterProcess();
- if (r.state != null) {
- r.state.setClassLoader(cl);
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(activity, e)) {
- throw new RuntimeException(
- "Unable to instantiate activity" + component
- + ":" + e.toString(), e);
- }
- }
newActivity 方法直接用类加载器加载类
- //newActivity 方法直接用类加载器加载类
- public Activity newActivity(ClassLoader cl, String className,
- Intent intent)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- return (Activity)cl.loadClass(className).newInstance();
- }
(3) 调用 LoadApk 的 makeApplication 创建 Application 对象, 如果 Application 对象已经存在则不会重新创建
- public Application makeApplication(boolean forceDefaultAppClass,
- Instrumentation instrumentation) {
- // 如果已经存在 mApplication, 则不创建, 所以一个应用只有一个 Application
- if (mApplication != null) {
- return mApplication;
- }
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
- Application app = null;
- String appClass = mApplicationInfo.className;
- if (forceDefaultAppClass || (appClass == null)) {
- appClass = "android.app.Application";
- }
- try {
- java.lang.ClassLoader cl = getClassLoader();
- if (!mPackageName.equals("android")) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- "initializeJavaContextClassLoader");
- initializeJavaContextClassLoader();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
- app = mActivityThread.mInstrumentation.newApplication(
- cl, appClass, appContext);
- appContext.setOuterContext(app);
- } catch (Exception e) {
- if (!mActivityThread.mInstrumentation.onException(app, e)) {
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- throw new RuntimeException(
- "Unable to instantiate application" + appClass
- + ":" + e.toString(), e);
- }
- }
- mActivityThread.mAllApplications.add(app);
- mApplication = app;
- if (instrumentation != null) {
- try {
- // 调用 Application 的 OnCreate 方法
- instrumentation.callApplicationOnCreate(app);
- } catch (Exception e) {
- if (!instrumentation.onException(app, e)) {
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- throw new RuntimeException(
- "Unable to create application" + app.getClass().getName()
- + ":" + e.toString(), e);
- }
- }
- }
- ...
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- return app;
- }
(4) 创建 ContextImpl 对象并通过 Activity 的 attach 方法完成关联和其他初始化操作
- // 调用 createBaseContextForActivity 方法创建 ContextImpl
- Context appContext = createBaseContextForActivity(r, activity);
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- Configuration config = new Configuration(mCompatConfiguration);
- if (r.overrideConfig != null) {
- config.updateFrom(r.overrideConfig);
- }
- Window window = null;
- if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
- window = r.mPendingRemoveWindow;
- r.mPendingRemoveWindow = null;
- r.mPendingRemoveWindowManager = null;
- }
- 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);
Activity 的 attach 方法会完成绑定 ContextImpl, 创建 Window, 关联 Application 等任务
- //Activity.class
- final void attach(Context context, ActivityThread aThread,
- ...
- Window window) {
- // 绑定 ContextImpl
- attachBaseContext(context);
- mFragments.attachHost(null /*parent*/);
- // 创建 Window 并设置回调监听
- mWindow = new PhoneWindow(this, window);
- mWindow.setWindowControllerCallback(this);
- mWindow.setCallback(this);
- mWindow.setOnWindowDismissedCallback(this);
- mWindow.getLayoutInflater().setPrivateFactory(this);
- if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
- mWindow.setSoftInputMode(info.softInputMode);
- }
- if (info.uiOptions != 0) {
- mWindow.setUiOptions(info.uiOptions);
- }
- mUiThread = Thread.currentThread();
- mMainThread = aThread;
- mInstrumentation = instr;
- mToken = token;
- mIdent = ident;
- mApplication = application;
- mIntent = intent;
- ...
- }
(5) 调用 Activity 的 onCreate 方法
- activity.mCalled = false;
- if (r.isPersistable()) {
- mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
- } else {
- mInstrumentation.callActivityOnCreate(activity, r.state);
- }
这样 Activity 就启动完毕了.
总结
通过对在应用里面启动新的 Activity 的过程进行源码跟踪, 我们发现这里面主要涉及到几个类: Activity,ActivityThread,ApplicationThread,ActivityManagerService.
(1)Activity 是我们发起启动新的 Activity 的入口, 也是最后完成 Activity 操作结束的地方. 我们通过 Activity 的 startActivity 发起启动新 Activity 的请求, 最后通过 Activity 的 attach 方法完成 Context 的绑定和窗口 Window 的创建和绑定.
(2)ActivityThread 是启动 Activity 的处理者, 也是一个中间人的角色, 通过调用其他几个类完成启动 Activity 的任务. 它首先通过 Binder 机制调用 ActivityManagerService 完成 Activity 相关的系统级的操作, 比如任务栈, 暂停其他 Activity 等, 然后通过内部的 Binder 类 ApplicationThread 接收 ActivityManagerService 的进程间请求, 将启动的操作重新转回到当前应用进程. 接着通过调用 Instrumentation 和 LoadApk 的相关方法完成加载 Activity 类和 Application 的任务. 最后调用 Activity 的 attach 方法完成一系列的绑定操作.
(3)ApplicationThread 是一个 Binder 类, 用于和 ActivityManagerService 的进程间通信.
(4)ActivityManagerService 是系统的一个服务, 用于管理 Activity 的状态和相关信息, 比如任务栈等.
如果是直接点击桌面的应用图标启动应用呢? 其实这个过程和启动 Activity 类似, 都是需要启动一个 Activity. 不过启动应用启动的是应用的入口 Activity, 同时是从桌面应用启动另一个应用程序的 Activity, 所以过程肯定会多一些步骤, 比如要找到应用中的入口 Activity, 创建新的应用程序进程, 要创建任务栈, 要移除桌面的焦点等. 等这些准备工作都好了以后, 后面就相当于是启动一个 Activity 的过程了. 有兴趣的童鞋可以研究一下.
来源: http://www.jianshu.com/p/7015a7be0ab3