android 启动app过程,Android Activity启动(三) 首次启动App时,activity跳转过程及原理解析...
在开始本文之前,要提一些相对偏一点的知识点,我们所看到的手机桌面Launcher,也是继承于Activity,当我们安装完一个其他的应用程序之后,就会在桌面Launcher上生成一个对应的应用程序的图标,首次点击这个图标的时候,Launcher就会启动该图标对应应用程序的首页Activty,一般启动的都是我们工程中的MainActivity,其实这个过程走的是一个Activity的启动的流程,与在
在开始本文之前,要提一些相对偏一点的知识点,我们所看到的手机桌面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的创建流程以及原理,感觉有不少相似的地方。
更多推荐
所有评论(0)