activity的启动流程之前已经通过源码了解了,那么app的启动流程是怎样的,从我们按下app的图标,到应用启动起来显示出画面,中间都经历了什么?

安卓是基于java的,所以和java有一定的相似性,一个java程序的起点是main,那么android是不是也是如此?事实上,正如猜想我们找到ActivityTread这个类中的main方法,这里就是app启动的源头

public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");SamplingProfilerIntegration.start();CloseGuard.setEnabled(false);//初始化内存卡环境Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());//处理签名相关的东西,验证之类的饿AndroidKeyStoreProvider.install();// Make sure TrustedCertificateStore looks in the right place for CA certificates//用户目录相关的东西final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0("<pre-initialized>");//应用程序一启动就初始化全局的looperLooper.prepareMainLooper();ActivityThread thread = new ActivityThread();//这个是主要的方法,false表示不是系统应用,第三方app默认都是falsethread.attach(false);//初始化主线程handler,在ActivityTread加载的时候就已经生成了if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}

正式开始加载app

private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {//第三方应用//ViewRootImpl相关......//这个已经很熟悉了,我们要去找IActivityManager的实现类ActivityManagerServicefinal IActivityManager mgr = ActivityManagerNative.getDefault();try {//进入ActivityManagerServicemgr.attachApplication(mAppThread);} catch (RemoteException ex) {// Ignore}//可以看到这里是内存使用量的一个监听,当app已经占用的空间大于系统分配给//这个app最大空间的四分之三的时候,java虚拟机会触发gc清理空间BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {if (!mSomeActivitiesChanged) {return;}Runtime runtime = Runtime.getRuntime();long dalvikMax = runtime.maxMemory();long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed > ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)+ " total=" + (runtime.totalMemory()/1024)+ " used=" + (dalvikUsed/1024));mSomeActivitiesChanged = false;try {mgr.releaseSomeActivities(mAppThread);} catch (RemoteException e) {}}}});} else {//系统应用// Don't set application object here -- if the system crashes,// we can't display an alert, we just want to die die die.android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());try {mInstrumentation = new Instrumentation();ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);mInitialApplication = context.mPackageInfo.makeApplication(true, null);mInitialApplication.onCreate();} catch (Exception e) {throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);}}// add dropbox logging to libcoreDropBox.setReporter(new DropBoxReporter());//设置Configuration改变的监听ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {@Overridepublic void onConfigurationChanged(Configuration newConfig) {synchronized (mResourcesManager) {// We need to apply this change to the resources// immediately, because upon returning the view// hierarchy will be informed about it.if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {// This actually changed the resources!  Tell// everyone about it.if (mPendingConfiguration == null ||mPendingConfiguration.isOtherSeqNewer(newConfig)) {mPendingConfiguration = newConfig;sendMessage(H.CONFIGURATION_CHANGED, newConfig);}}}}@Overridepublic void onLowMemory() {}@Overridepublic void onTrimMemory(int level) {}});}

进入ActivityManagerService

@Overridepublic final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);}}
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {......//thread就是传过来的final ApplicationThread mAppThread = new ApplicationThread();它在ActivityThread加载的时候就已经创建thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());......// See if the top visible activity is waiting to run in this process...if (normalMode) {try {if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}// Find any services that should be running in this process...if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}......

回到ActivityThread中

 public final void bindApplication(String processName, ApplicationInfo appInfo,List<ProviderInfo> providers, ComponentName instrumentationName,ProfilerInfo profilerInfo, Bundle instrumentationArgs,IInstrumentationWatcher instrumentationWatcher,IUiAutomationConnection instrumentationUiConnection, int debugMode,boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,Bundle coreSettings) {if (services != null) {// Setup the service cache in the ServiceManagerServiceManager.initServiceCache(services);}setCoreSettings(coreSettings);/** Two possible indications that this package could be* sharing its runtime with other packages:** 1.) the sharedUserId attribute is set in the manifest,*     indicating a request to share a VM with other*     packages with the same sharedUserId.** 2.) the application element of the manifest has an*     attribute specifying a non-default process name,*     indicating the desire to run in another packages VM.** If sharing is enabled we do not have a unique application* in a process and therefore cannot rely on the package* name inside the runtime.*/IPackageManager pm = getPackageManager();android.content.pm.PackageInfo pi = null;try {pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());} catch (RemoteException e) {}if (pi != null) {boolean sharedUserIdSet = (pi.sharedUserId != null);boolean processNameNotDefault =(pi.applicationInfo != null &&!appInfo.packageName.equals(pi.applicationInfo.processName));boolean sharable = (sharedUserIdSet || processNameNotDefault);// Tell the VMRuntime about the application, unless it is shared// inside a process.if (!sharable) {VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,appInfo.processName);}}AppBindData data = new AppBindData();data.processName = processName;data.appInfo = appInfo;data.providers = providers;data.instrumentationName = instrumentationName;data.instrumentationArgs = instrumentationArgs;data.instrumentationWatcher = instrumentationWatcher;data.instrumentationUiAutomationConnection = instrumentationUiConnection;data.debugMode = debugMode;data.enableOpenGlTrace = enableOpenGlTrace;data.restrictedBackupMode = isRestrictedBackupMode;data.persistent = persistent;data.config = config;data.compatInfo = compatInfo;data.initProfilerInfo = profilerInfo;sendMessage(H.BIND_APPLICATION, data);}

handler接收消息进行处理

case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;
private void handleBindApplication(AppBindData data) {......//反射加载到Instrumentation对象或者当条件不满足时,直接new出来try {java.lang.ClassLoader cl = instrContext.getClassLoader();mInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();} catch (Exception e) {throw new RuntimeException("Unable to instantiate instrumentation "+ data.instrumentationName + ": " + e.toString(), e);}....else {mInstrumentation = new Instrumentation();}......try {//调用Application的onCreate 方法mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!mInstrumentation.onException(app, e)) {throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}
}

Application是启动了,那么到了这里似乎已经无法继续往下走了,activity是如何启动的,我们回到ActivityManagerService中,在上边的那代码下如下,现在已经知道了bindApplication最终执行到了Application的onCreate,那么下边的方法attachApplicationLocked将会是寻找Activity启动的线索

private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {......//thread就是传过来的final ApplicationThread mAppThread = new ApplicationThread();它在ActivityThread加载的时候就已经创建thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());......// See if the top visible activity is waiting to run in this process...if (normalMode) {try {if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}// Find any services that should be running in this process...if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}......

attachApplicationLocked

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);if (!isFrontStack(stack)) {continue;}ActivityRecord hr = stack.topRunningActivityLocked(null);if (hr != null) {if (hr.app == null && app.uid == hr.info.applicationInfo.uid&& processName.equals(hr.processName)) {try {//真的开始启动activity了if (realStartActivityLocked(hr, app, true, true)) {didSomething = true;}} catch (RemoteException e) {Slog.w(TAG, "Exception in new application when starting activity "+ hr.intent.getComponent().flattenToShortString(), e);throw e;}}}}}if (!didSomething) {ensureActivitiesVisibleLocked(null, 0);}return didSomething;}

到了realStartActivityLocked这个方法这里,后边的东西就和之前看过的activity的启动流程相同了,所以就不再往下看了,感兴趣可以看看我的另一篇03.源码阅读(Activity启动流程--android api 23)

12.源码阅读(app启动流程-android api 26)相关推荐

  1. android源码学习- APP启动流程(android12源码)

    前言: 百度一搜能找到很多讲APP启动流程的,但是往往要么就是太老旧(还是基于android6去分析的),要么就是不全(往往只讲了整个流程的一小部分).所以我结合网上现有的文章,以及源码的阅读和调试, ...

  2. bluetoothd源码剖析(一)启动流程

    蓝牙系列: bluez调试笔记_weixin_41069709的博客-CSDN博客_bluezbluez移植https://blog.csdn.net/weixin_41069709/article/ ...

  3. Wifi模块—源码分析Wifi启动(Android P)

    一.前言 Android P在wifi这块改动挺大的,Wifi到AndoidO之后不再使用jni,所以AndroidP也一样不再使用jni来实现Java代码与本地的C/C++代码交互,而是使用HIDL ...

  4. Android进阶——Small源码分析之启动流程详解

    前言 插件化现在已经是Android工程师必备的技能之一,只是学会怎么使用是不行的,所以蹭有时间研究一下Small的源码.对于插件化主要解决的问题是四大组件的加载和资源的加载,读懂所有Small源码需 ...

  5. zygoteinit.java_源码跟踪之启动流程:从ZygoteInit到onCreate

    Instrumentation SDK版本名称: Pie API Level: 28 一.源码调用时序图 1. Activity的启动流程 说明:其中ActivityThread中执行的schedul ...

  6. 【安卓 R 源码】Activity 启动流程及其生命周期源码分析

    1. Activty 的生命周期 activity的生命周期 oncreate()->onstart()->onResume()->onPause()->onStop()-&g ...

  7. Kubelet源码分析(一):启动流程分析

    源码版本 kubernetes version: v1.3.0 简介 在Kubernetes急群众,在每个Node节点上都会启动一个kubelet服务进程.该进程用于处理Master节点下发到本节点的 ...

  8. 【Flink源码】JobManager启动流程

    写在前面 在 [Flink源码]再谈 Flink 程序提交流程(中) 一文中,笔者后来发现谬误颇多,且随着 Flink 版本的更迭,部分方法实现方式已发生较大改变.因此,思虑再三决定针对 JobMan ...

  9. Flask1.1.4 Werkzeug1.0.1 源码分析:启动流程

    基于QuickStart中的一个demo来分析 from flask import Flaskapp = Flask(__name__)@app.route("/") def he ...

最新文章

  1. 京东数科首次公开:强一致、高性能分布式事务中间件JDTX
  2. bat文件先杀掉端口号,然后启动jar包
  3. 上传Text文档并转换为PDF
  4. Python之路(第十六篇)xml模块、datetime模块
  5. Android 编译FFmpeg x264
  6. python requests 异步调用_构建高效的python requests长连接池详解
  7. 软件测试用例(全面)
  8. QCC3005 芯片开发过程中碰到的一些问题
  9. 博士申请 | 美国明尼苏达大学葛畅教授招收隐私数据管理方向全奖博士/硕士/博后/访问学者...
  10. 计算机msvcp110.dll丢失,msvcp110.dll丢失怎样修复
  11. mysql workbench安装配置_Mysql WorkBench安装配置图文教程
  12. 三十分钟理解:稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB
  13. BIGD牛魔王UI图标设计iocn主题设计全套高清视频教程
  14. 爬虫学习笔记,从基础到部署。
  15. 【java学习】String字符串
  16. 堡垒机,ssh协议,telnet协议,b/s架构
  17. Nasdaq股票代码表 zt
  18. 数据中台=大数据平台+数据资产管理平台+数据服务平台
  19. 直播程序源码Android10.0 导航栏和状态栏动态控制合集
  20. 阿里淘宝高层变动 马云卸任

热门文章

  1. 手把手教你Tomcat配置环境变量以及验证方法
  2. 关于CMMI级别阶梯式前进路线图的对话
  3. gin-vue-blog自建博客
  4. goj基础环境的配置
  5. 方案一TCP 完成聊天室的编写
  6. java 模板引擎_极简 Spring Boot 整合 Thymeleaf 页面模板
  7. 神策数据丨九大行业数字化经营指南集锦,值 100% 收藏
  8. 视频回顾 | 微信生态数字化运营进阶课大全!
  9. 寻人 | 一个有趣的职业可能性,与你分享
  10. 掌握这些PPT技巧,让你的工作效率提高10倍