分析流程基于Android8.0源码
一般情况下我们通过Activity中的startActivity方法启动一个Activity。这个流程中涉及一下几个类:
android.app.Activity
android.app.Instrumentation
com.android.server.am.ActivityManagerService
com.android.server.am.ActivityStarter
com.android.server.am.ActivityStackSupervisor
android.app.ActivityThread
android.app.ActivityThread$ApplicationThread
通过下图了解一下各个类之间的调用关系
整个流程如上图所示,多数代码直接跟着进就可以看到,这里主要说一下两次IPC,通过每个类的包名可以间接反映出整个启动过程是一个C/S结构的跨进程操作。第一次跨进程是在Instumentation内部调用ActivityManagerService的startActivity方法时,代码如下:
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
看一下ActivityManager:
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;
}
};
这里通过ServiceManager.getService(Context.ACTIVITY_SERVICE)返回一个IActivityManager,就是一个ActivityManagerService,IActivityManager在/frameworks/base/core/java/android/app/目录下,是一个AIDL文件,里边声明了startActivity方法
interface IActivityManager {
...
int startActivity(...);
...
}
ActivityManagerService继承了IActivityManager.Stub,实现StartActivity方法。这个方法的调用是在系统进程,之后的逻辑在系统进程里执行。
中间跟踪的代码如图,到ActivityStackSupervisor类中的realStartActivityLocked方法:
final boolean realStartActivityLocked(...) throws RemoteException {
...
app.thread.scheduleLaunchActivity();
...
}
这里app.thread是一个ApplicationThread对象,ApplicationThread是ActivityThread的一个内部类,看一下ApplicationThread的相关代码:
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void scheduleLaunchActivity(...) {
...
}
ApplicationThread继承了IApplicationThread.Stub,这里也是跨进程的一步,这个时候就从系统进程回到了应用自己的进程,然后通过反射获取Activity实例,实例化Context,并调用获取Activity实例的attach方法,传入Context。最后调用到Activity的声明周期的方法。
总结:应用内启动Activity的逻辑主要经历了两次的跨进程过程,首先从应用自己进程跨进程到系统进程,处理Activity创建过程中的标志位判断,Activity所在的ActivityStack判断、初始化,等等,最后跨进程会应用自己进程实例化Activity,并调用Activity的生命周期方法。