Activity的启动过程

今天我们来分析下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,创建新的应用程序进程,要创建任务栈,要移除桌面的焦点等。等这些准备工作都好了以后,后面就相当于是启动一个Activity的过程了。有兴趣的童鞋可以研究一下。
欢迎关注我的微信公众号,和我一起每天进步一点点!

Activity的启动过程
文章图片
AntDream

    推荐阅读