[置顶] Android:图解Activity启动流程源码(整体流程)
Intent intent = new Intent(this, TestActivity.class);startActivity(intent);
以上代码对于Android开发者再熟悉不过了,功能即启动 TextActivity。这是最基本的Intent使用知识,通过显示Intent来触发 Activity的启动,而Activity,四大组件中的老大,是一种展示型组件,用于向用户展示交互界面,如此重要的一个角色,类似于以上的代码,每天都在写,可是有几个问题是否想过:
- 系统内部是如何启动一个Activity?
- 当启动一个新Activity时,该对象是在何时创建的?
- Application 的onCreate方法又是在何时被系统回调?
- Activity 的onCreate方法又是在何时被系统回调?
接下来从源码的角度来分析解决以上问题,注意:由于Android内部实现比较复杂,所以以下分析更侧重于整体流程,对Activity启动建立一个整体的意识。
一. Activity启动流程步骤
Step 1. 启动Activity
Intent intent = new Intent(this, TestActivity.class);startActivity(intent);
Step 2. Activity的startActivityForResult 方法
Activity的启动调用的就是startActivity方法,此方法有多种重载方式,但最后都会调用 startActivityForResult 方法,实现如下:
【Activity 类】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) { // mStartedActivity = true; } ...... } else { ...... } }
以上代码中第一行 if判断 mParent == null
即可,mParent 代表的是ActivityGroup,它最开始用来在一个界面中嵌入多个子Activity,而在API13中已经被抛弃了,因为Fragment的出现和它的高效,已经代替了ActivityGroup。
其中还要注意if判断语句中的一个参数 mMainThread.getApplicationThread()
,它的类型为 ApplicationThread,而ApplicationThread 是 ActivityThread的一个内部类。(通过后面分析可知,这两个类在Activity的启动过程中起重要作用)
Step 3. Instrumentation的execStartActivity方法
介绍两个基本点后,接下来查看Instrumentation 的 execStartActivity 方法。
【Instrumentation 类】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) { ...... } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); //☆☆☆☆☆ 重点!!!!! int result = ActivityManagerNative.getDefault() .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; }
以上代码可得,启动Activity真正的实现由 ActivityManagerNative.getDefault()
的 startActivity 方法来完成,往下深入之前,先介绍一下此类相关知识:ActivityManagerService(简称AMS)继承自ActivityManagerNative,而ActivityManagerNative继承自Binder并实现了IActivityManager的具体实现。
接下来查看ActivityManagerNative的getDefault() 方法:
【ActivityManagerNative 类】static public IActivityManager getDefault() { return gDefault.get(); }private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } };
以上代码可知: 而 ActivityManagerNative.getDefault()
其实是一个IActivityManager类型的Binder对象,因此它的具体实现是ActivityManagerService类!而且在ActivityManagerNative类实现中,AMS此Binder对象采用Singleton单例模式对外提供。
Step 4. ActivityManagerService的startActivity方法
根据以上分析后,由原来Activity是 ActivityManagerNative.getDefault()
来启动,转移到了AMS!继续深入,直接查看AMS的startActivity方法:
【ActivityManagerService类】 @Override public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, Bundle options) { //☆☆☆☆☆ 重点!!!!! return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId()); } @Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) { ..... //☆☆☆☆☆ 重点!!!!! return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd, null, null, options, userId); }
可以看出Activity的启动过程又转移到了 ActivityStackSupervisor的 startActivityMayWait方法中。但是继续往下深入之前先暂停一会,以上步骤用时序图画出来理清一下思路:
Step 5. ActivityStackSupervisor 和 ActivityStack 之间互相调用
当Activity的启动过程又转移到了 ActivityStackSupervisor后,此类不断调用自身方法并且与 ActivityStack 之间的方法回调。但是,这涉及到的方法略多,而这篇博文作为认识整体流程,就不贴相关代码了,重点不同,将两个类之间的方法回调以流程图展示,更清晰,下面会直接讲解重点方法:
以上流程图是ActivityStackSupervisor 和 ActivityStack 之间的互相调用,了解基本流程即可,这里直接看此过程的最后一个调用方法:realStartActivityLocked
【ActivityStackSupervisor 类】 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, new Configuration(mService.mConfiguration), r.compat, app.repProcState, r.icicle, results, newIntents, !andResume, mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop); ...... }
以上这行代码很重要,正式转移了Activity启动过程,其中需要详细介绍app.thread,它的类型就是IApplicationThread。
Step 6. ApplicationThreadNative内部类 ApplicationThreadProxy
IApplicationThread源码实现如下:
【IApplicationThread 类】public interface IApplicationThread extends IInterface { void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) throws RemoteException; void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException; void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException; void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException; void scheduleResumeActivity(IBinder token, int procState, boolean isForward) throws RemoteException; void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException; void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, int procState, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) throws RemoteException; void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config) throws RemoteException; void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException; void scheduleDestroyActivity(IBinder token, boolean finished, int configChanges) throws RemoteException; void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) throws RemoteException; static final int BACKUP_MODE_INCREMENTAL = 0; static final int BACKUP_MODE_FULL = 1; static final int BACKUP_MODE_RESTORE = 2; static final int BACKUP_MODE_RESTORE_FULL = 3; void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo, int backupMode) throws RemoteException; void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo) throws RemoteException; void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) throws RemoteException; void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) throws RemoteException; void scheduleUnbindService(IBinder token, Intent intent) throws RemoteException; void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, int flags, Intent args) throws RemoteException; void scheduleStopService(IBinder token) throws RemoteException; ......
因为IApplicationThread 类继承了 IInterface接口,所以它是一个Binder类型的接口。从IApplicationThread 声明的接口可以看出,其内部包含了大量启动、停止Activity的接口,此外还包含了启动和停止服务的接口,IApplicationThread 这个 Binder接口实现者完成了大量和Activity、Service启动/停止有关的功能。
可是IApplicationThread 的实现者到底是什么?
答案就是 ActivityThread 中的内部类 ApplicationThread。来查看一下ApplicationThread的定义:
private class ApplicationThread extends ApplicationThreadNative { ..... } public abstract class ApplicationThreadNative extends Binder implements IApplicationThread { ...... }
由以上代码可以看出 ApplicationThread 继承了 ApplicationThreadNative ,而ApplicationThreadNative 继承了Binder并且实现了IApplicationThread 接口,但是在它内部,还有一个内部类ApplicationThreadProxy,实现如下:
【ApplicationThreadProxy 类】class ApplicationThreadProxy implements IApplicationThread { private final IBinder mRemote; public ApplicationThreadProxy(IBinder remote) { mRemote = remote; } public final IBinder asBinder() { return mRemote; } //☆☆☆☆☆ 重点!!!!! public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(finished ? 1 : 0); data.writeInt(userLeaving ? 1 :0); data.writeInt(configChanges); mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } public final void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(showWindow ? 1 : 0); data.writeInt(configChanges); mRemote.transact(SCHEDULE_STOP_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } ......}
ApplicationThreadProxy 也是系统为AIDL文件自动生成的代理类。
通过以上分析可知,ApplicationThreadNative就是IApplicationThread的实现者,由于ApplicationThreadNative被系统定义为抽象类,所以ApplicationThread就成了IApplicationThread的最终实现者。
Step 7. ActivityThread 内部类 ApplicationThread
绕了一大圈,Activity的启动过程最终回到了ApplicationThread ,它通过 scheduleLaunchActivity
方法来启动 Activity,代码如下:
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, int procState, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profileFile = profileName; r.profileFd = profileFd; r.autoStopProfiler = autoStopProfiler; updatePendingConfiguration(curConfig); //☆☆☆☆☆ 重点!!!!! queueOrSendMessage(H.LAUNCH_ACTIVITY, r); }
在 ApplicationThread中,此方法实现非常简单,就是发送一个Activity的消息交由 Handle 处理(最后一行代码),这个Handle实现于 ActivityThread 内部,名为H。
Step 8. ActivityThread 内部 Handle
此Handle对消息处理的实现:
public static final int LAUNCH_ACTIVITY = 100; public static final int PAUSE_ACTIVITY = 101; public static final int PAUSE_ACTIVITY_FINISHING= 102; public static final int STOP_ACTIVITY_SHOW = 103; public static final int STOP_ACTIVITY_HIDE = 104; public static final int SHOW_WINDOW = 105; public static final int HIDE_WINDOW = 106; public static final int RESUME_ACTIVITY = 107; ...... 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"); ActivityClientRecord r = (ActivityClientRecord)msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); //☆☆☆☆☆ 重点!!!!! handleLaunchActivity(r, null); 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"); handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ...... } }
非常熟悉的Handle实现方法,注意在ApplicationThread发送消息的标志是H.LAUNCH_ACTIVITY,直接查看handleMessage
方法中对应的处理代码。此时可以发现,Activity的启动过程是由ActivityThread的handleLaunchActivity
方法实现,查看其代码:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); if (r.profileFd != null) { mProfiler.setProfiler(r.profileFile, r.profileFd); mProfiler.startProfiling(); mProfiler.autoStopProfiler = r.autoStopProfiler; } // Make sure we are running with the most recent config. handleConfigurationChanged(null, null); if (localLOGV) Slog.v( TAG, "Handling launch of " + r); //☆☆☆☆☆ 重点!!!!! Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); Bundle oldState = r.state; handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed); ...... } }
总算到了最后一步,从以上代码可以看出,performLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过 handleResumeActivity方法来调用被启动Activity的onResume这一生命周期方法。
后半部分时序图如下:
接下来详细介绍performLaunchActivity方法完成的五大事件:
(1)从ActivityClientRecord中获取待启动的Activity的组件信息
【ActivityThread 类的 performLaunchActivity方法中】 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对象
【ActivityThread 类的 performLaunchActivity方法中】 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); 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); } }
至于 Instrumentation 的 newActivity,它的实现比较简单,就是通过类加载器创建Activity对象,代码如下:
【Instrumentation 类】 public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Activity)cl.loadClass(className).newInstance(); }
(3)通过 LoadedAPK 的 makeApplication 方法来尝试创建 Application对象
【ActivityThread 类的 performLaunchActivity方法中】 Application app = r.packageInfo.makeApplication(false, mInstrumentation);
查看LoadedAPK 的 makeApplication 方法具体实现:
【LoadedAPK 类】 public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } Application app = null; String appClass = mApplicationInfo.className; if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; } try { java.lang.ClassLoader cl = getClassLoader(); ContextImpl appContext = new ContextImpl(); appContext.init(this, null, mActivityThread); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); } catch (Exception e) { if (!mActivityThread.mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to instantiate application " + appClass + ": " + e.toString(), e); } } mActivityThread.mAllApplications.add(app); mApplication = app; if (instrumentation != null) { try { instrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!instrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } return app; }
从此方法的实现可以看出,如果Application已经被创建过,就不会再创建,以为者一个应用只有一个Application对象。Application对象的创建也是通过Instrumentation完成的,这个过程和Activity对象的创建一样,都是通过类加载器实现的。Application创建完毕后,系统会通过 Instrumentation 的 callApplicationOnCreate
来调用Application的 onCreate
方法。
(4)通过 ContextImpl对象并通过Activity的 attach 方法来完成一些重要数据的初始化
【ActivityThread 类的 performLaunchActivity方法中】Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config);
ContextImpl是一个很重要的数据结构,它是Context 的具体实现,Context中大部分逻辑都是由ContextImpl来实现的。ContextImpl是通过Activity的attach方法来和Activity建立关系的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接收到外部输入事件后就可以将事件传递给Activity。
(5)调用 Activity 的 onCreate方法
【ActivityThread 类的 performLaunchActivity方法中】mInstrumentation.callActivityOnCreate(activity, r.state);
如上代码,Activity的onCreate
方法被调用,意味着Activity已经完成了整个启动过程!
二. Activity启动流程总时序图:
其实以上关于Activity底层的问题你不知道也可以写好代码,但是学习了解系统的底层工作原理,相当于学习Android操作系统,可以提高我们对操作系统在技术实现上的理解。如果学习Android使用方法相当于练习武功招式,那么学习底层工作原理就相当于修炼内功,haha,要知道高手之间过招比的是什么? 当然是看谁内功深厚啦~
最后,在此声明,以上内容总结于《Android艺术开发与探索》,时序图是自己归纳的,这个我参考了网上其它的博文讲解,但是跟书上稍有差别,大概是讲解的侧重点不同,如有错误,还请指正。
关于书上这个章节我看过起码5遍,但每次过了不久就忘了,所以此次总结下来,印象深刻一些,但是我感觉自己还是没有完全理解,只是了解了一个大致流程,以后再做补充吧。
检验一个知识点是否学会,写下来和讲出来恐怕是最有效的方法了。
希望对你们有帮助 :)
共同学习
更多相关文章
- 第一行代码 第三章 RecyclerView
- 八款Android(安卓)开发者必备的小工具
- Android(安卓)4.0.3 联系人(通讯录)应用源码学习
- OpenJDK将对Android开发产生怎样的影响?
- View基础知识总结
- 下载AOSP android源码(最小最快下载方式,跳过编译直接导入Android(
- 深入讲解WebView——下
- [Android][转]Android(安卓)View绘制13问13答
- Android彻底退出应用程序(转)