先放一张应用进程启动的流程图。
当 Launcher应用点击某个应用图标时,会发送消息给 AMS,启动这个应用的 Launcher Activity。假如此时这个应用还未启动,AMS 会给 Zygote进程发送请求,要求先创建进程。 Zygote进程 会 fork出 一个进程,同时会对进程做一些初始化工作。之后这个会对这个新创建的进程会 启动binder机制,之后会执行应用进程入口函数:ActivityThread#main
(进程会有一个默认线程创建去执行本进程的代码,这个默认的进程称之为主进程)在应用程序入口函数会启动主线程消息队列的Looper循环,之后会报告 AMS,进程已经启动完成可以进行接下来工作了。AMS 收到消息后,给应用进程发送消息,应用进程收到消息会干两件事:1、创建Application实例。2、启动 Launcher Activity。
以上是整个启动流程,具体从 ActivityThread#main
入口之后干得事情,就以代码片段的形式贴出来,来捋一下上述过程。
基于安卓版本:26
ActivityThread#main
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
...
}
ActivityThread#attach
private void attach(boolean system) {
final IActivityManager mgr = ActivityManager.getService();
mgr.attachApplication(mAppThread); // 进行IPC通信,通知AMS
...
}
ActivityManagerService#attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
...
thread.bindApplication(...); // 1、回调ActivityThread
...
mStackSupervisor.attachApplicationLocked(app) // 2、启动首页
}
attachApplicationLocked
这里会有两个步骤需要注意的:1、回调App进程去创建Application 2、启动Launcher Activity
先看第一步:回调App进程去创建Application
ApplicationThread#bindApplication
public final void bindApplication(...){
...
sendMessage(H.BIND_APPLICATION, data);
}
因为通过Binder机制进行IPC调用时,方法都在Binder线程中运行。通过Handler机制,将消息发送给主线程去执行。之后会调用 handleBindApplication
方法
ActivityThread#handleBindApplication
private void handleBindApplication(...){
...
//创建Application对象,并回调attachBaseContext
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
//回调 onCreate
mInstrumentation.callApplicationOnCreate(app);
}
LoadedApk#makeApplication
public Application makeApplication(...){
...
// 创建上下文 Context
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 创建Application。并调用 attach、attachBaseContext来设置 mBase
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
}
至此,Application创建完成,同时通过 attachBaseContext
给mBase 设置了Application上下文Context:ContextImpl
,之后调用了 onCreate
声明周期方法。
再第二步:启动Launcher Activity
ActivityStackSupervisor#attachApplicationLocked
boolean attachApplicationLocked(...){
...
ActivityRecord hr = stack.topRunningActivityLocked();
realStartActivityLocked(hr, app, true, true)
}
ActivityStackSupervisor#realStartActivityLocked
final boolean realStartActivityLocked(...){
...
// IPC 调用app进程ApplicationThread 启动页面
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,...);
}
Application#scheduleLaunchActivity
public final void scheduleLaunchActivity(...){
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
接收到 AMS 启动页面的消息后,通过Handler机制把消息发送给主线程去执行:handleLaunchActivity
ActivityThread#handleLaunchActivity
private void handleLaunchActivity(...) {
...
// 创建Activity,并执行attach、onCreate方法回调
Activity a = performLaunchActivity(r, customIntent);
// 执行 onResume 方法回调
handleResumeActivity(r.token, ...);
}
ActivityThread#performLaunchActivity
private Activity performLaunchActivity(...){
...
// 创建Activity 对应上下文环境 Context
ContextImpl appContext = createBaseContextForActivity(r);
// 创建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
// 调用attach方法,初始化工作,其中就有设置 mBase
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, r.configCallback);
// 回调 onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state);
}
ActivityThread#handleResumeActivity
private Activity handleResumeActivity(...){
...
r = performResumeActivity(token, clearHide, reason);
}
public final ActivityClientRecord performResumeActivity(...){
...
r.activity.performResume(); // 调用onResume 回调
}
至此,启动的页面 onCreate 、 onResume 都已执行完成。
之前会在进程创建时,启动Binder机制,具体怎么启动呢,配一张图:
整体的主进程启动流程如下: