在开始本文之前,要提一些相对偏一点的知识点,我们所看到的手机桌面Launcher,也是继承于Activity,当我们安装完一个其他的应用程序之后,就会在桌面Launcher上生成一个对应的应用程序的图标,首次点击这个图标的时候,Launcher就会启动该图标对应应用程序的首页Activty,一般启动的都是我们工程中的MainActivity,其实这个过程走的是一个Activity的启动的流程,与在App内部启动一个Activity的不同之处在于,点击桌面Launcher首次启动一个应用程序的时候,会先去创建一个该应用程序对应的进程,然后执行ActivityThread的main()方法去创建该应用对应的Application,然后再去启动首页Activity。在这整个过程中,Application的创建过程,以及Activity的大部分的启动过程已经在Android Activity启动(一),Application创建的过程以及原理分析和 Android Activity启动(二)App内部activity跳转过程及原理分析这前两篇博客中讲到了。

首次启动app时,Activity的跳转流程与在App内部启动一个Activity的流程,在前半部分是基本一致的,所以Activity启动的前半部分我不打算再描述一遍了,只从ActivityStackSupervisor类中的startSpecificActivityLocked()方法开始讲起,因为在这个方法中区分了到底是该去创建一个应用程序对应的进程,还是直接去启动一个Activity,关于开始启动一个Activity直到调用ActivityStackSupervisor的startSpecificActivityLocked()方法的这个前半部分的启动过程,有还不是很理解的同学可以先看下我的上一篇博客Android Activity启动(二)App内部activity跳转过程及原理分析,上篇博客已经讲的很详细了。本篇博客,我们从ActivityStackSupervisor的startSpecificActivityLocked()开始说起,下面我们来看下代码

void startSpecificActivityLocked(ActivityRecord r,

boolean andResume, boolean checkConfig) {

//获取该Activity对应的进程对象

ProcessRecord app = mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid, true);

r.getStack().setLaunchTime(r);

/*

* 因为我们本篇博客讲解的是App内部Activity的跳转过程

* 所以该Activity对应的进程对象肯定存在

* 下面的if语句里面的判断条件肯定会成立

*/

if (app != null && app.thread != null) {

try {

......

//启动新的Activity

realStartActivityLocked(r, app, andResume, checkConfig);

return;

} catch (RemoteException e) {

Slog.w(TAG, "Exception when starting activity "

+ r.intent.getComponent().flattenToShortString(), e);

}

}

/*

* startProcessLocked()方法会去创建一个进程

* 在点击桌面App图标,首次进入app中时会调用startProcessLocked()方法

* 因为首次启动App时,要去创建该App对应的进程

* 除了app首次启动之外,app内部跳转Activity的时候都不会执行到该方法,

*/

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,

"activity", r.intent.getComponent(), false, false, true);

}

上面的注释中已经解释的很清楚了,如果是App内部跳转Activity的话,会去执行realStartActivityLocked()方法来启动一个Activity,否则的话就会去调用ActivityManagerService的startProcessLocked()方法来创建一个该应用程序对应的进程。我们来看下这个方法。

final ProcessRecord startProcessLocked(String processName,

ApplicationInfo info, boolean knownToBeDead, int intentFlags,

String hostingType, ComponentName hostingName, boolean allowWhileBooting,

boolean isolated, boolean keepIfLarge) {

return startProcessLocked(processName, info, knownToBeDead, intentFlags,

hostingType,hostingName, allowWhileBooting, isolated,

0 /* isolatedUid */, keepIfLarge,null /* ABI override */,

null /* entryPoint */, null /* entryPointArgs */,null /*

crashHandler */);

}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,

boolean knownToBeDead, int intentFlags, String hostingType, ComponentName

hostingName,boolean allowWhileBooting, boolean isolated,

int isolatedUid, boolean keepIfLarge,String abiOverride,

String entryPoint, String[] entryPointArgs, Runnable crashHandler) {

long startTime = SystemClock.elapsedRealtime();

//该进程对应的ProcessRecord

ProcessRecord app;

if (!isolated) {

//创建该进程对应的ProcessRecord对象

app = getProcessRecordLocked(processName, info.uid, keepIfLarge);

......

} else {

......

}

......

startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint,

entryPointArgs);

return (app.pid != 0) ? app : null;

}

在上述方法中,创建了该进程对应的ProcessRecord对象,然后又调用了另一个startProcessLocked()方法

private final void startProcessLocked(ProcessRecord app, String hostingType,

String hostingNameStr, String abiOverride, String entryPoint, String[]

entryPointArgs) {

......

try {

......

if (entryPoint == null) entryPoint = "android.app.ActivityThread";

......

ProcessStartResult startResult;

if (hostingType.equals("webview_service")) {

......

} else {

//重点来了!!!调用Porcess.start()方法来创建一个进程

startResult = Process.start(entryPoint,

app.processName, uid, uid, gids, debugFlags,mountExternal,

app.info.targetSdkVersion, seInfo, requiredAbi,instructionSet,

app.info.dataDir, invokeWith, entryPointArgs);

}

......

} catch (RuntimeException e) {

......

}

}

在上述代码中,最终会调用Process.start()方法来创建一个进程,而ActivityThread的main()方法也是在进程常见的时候执行的(额,查了很多的资料,基本都是说是在进程创建的时候调用的ActivityThread的main()方法,但是我往下跟了跟代码,没有找到具体哪个地方调用的main()方法,我猜有可能是在native层调用的main()方法吧,另外,我们看Process.start()的第一个参数enrtyPoint,在上述截图的代码中已经很明显能看到,该参数的值是“android.app.ActivityThread”,也就是说再Process.start()的参数里,会把ActivityThread这个类的作为参数传递,所以我们也有理由相信,ActivityThread的main()方法可能也是在这个过程中执行的)

综上所述,应用程序的进程也就创建完毕了,ActivityThread的main()方法也执行了,具体在ActivityThread的main()方法中执行了哪些操作,欢迎大家看一下我的 Android Activity启动(一)Application创建的过程以及原理分析这篇博客,里面有详细的介绍

到此为止,有关App Activity跳转的流程以及原理的分析基本上已经写完了,本篇博客内容不算很多,大部分的内容在前两篇博客中已经讲过了,单独本篇内容抽离出来,也是为了更具层次和条理性。

下面我来总结一下这三篇博客的主要内容:

当我们点击桌面的Launcher首次进入app时,会走Activity的startActivity()的过程,在启动一个新的Activity之前,会先执行“当前Activity”的onPause()方法,把当前Activity给pause掉(这里需要提一点,如果是点击桌面Launcher,首次进入app的话,这个“当前的Activity”指的就是桌面Launcher的Activity),当前Activity执行onPause()之后,如果当前应用的进程已经创建(这种情况下指的是在App内部的activity的跳转),那么就会去通过ActivityManagerService中持有的ActivityThread中的ApplicationThread这个Binder对象来立即创建一个新的Activity,并执行该Activity声明周期的方法,如果当前应用的进程没有创建(也就是首次进入app),那么这个时候会先通过Process.start()方法来创建一个进程,在创建的过程中会去调用ActivityThread的main()方法,在这个main()方法中会创建一些必备的东西比如,主线程的Looper等,并且在main()方法中会执行Application的创建过程,通过ActivityManagerService来创建一个Application,在创建完成之后,会启动一个Activity,这个Activity指的就是我们默认启动的首页Activity,也就是我们通常说的MainActivity。

欢迎大家对我针对Activity跳转流程和原理的三篇博客进行指正,感激不尽,下篇博客开始讲BroadcastReceiver的创建流程以及原理,感觉有不少相似的地方。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐