前言

在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读Android 8.0源码时发现应用程序(根Activity)启动过程照Android 7.0有了一些变化,因此又写下了本篇文章,本篇文章照此前的文章不仅流程发生变化,而且增加了一些分析,算是升级版本。由于篇幅较长,Android8.0 根Activity启动过程仍旧分为前篇和后篇来进行讲解。

1. ActivityThread启动Activity的过程

通过前篇的介绍,我们知道目前的代码逻辑运行在应用程序进程中。先来查看ActivityThread启动Activity的过程的时序图。

我们接着来查看ApplicationThread的scheduleLaunchActivity方法,其中ApplicationThread是ActivityThread的内部类,应用程序进程创建后会运行代表主线程的实例ActivityThread,它管理着当前应用程序进程的线程。ApplicationThread的scheduleLaunchActivity方法如下所示。

frameworks/base/core/java/android/app/ActivityThread.java

@Overridepublic final void scheduleLaunchActivity(Intent intent, IBinder token, intident,ActivityInfo info, Configuration curConfig, Configuration overrideConfig,CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,intprocState, Bundle state, PersistableBundle persistentState,List<ResultInfo> pendingResults, List<ReferrerIntent>pendingNewIntents,boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {updateProcessState(procState,false);ActivityClientRecord r= newActivityClientRecord();r.token=token;r.ident=ident;r.intent=intent;r.referrer=referrer;...updatePendingConfiguration(curConfig);sendMessage(H.LAUNCH_ACTIVITY, r);
}

View Code

scheduleLaunchActivity方法会将启动Activity的参数封装成ActivityClientRecord ,sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord 传递过去,sendMessage方法有多个重载方法,最终调用的sendMessage方法如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {if(DEBUG_MESSAGES) Slog.v(TAG,"SCHEDULE" + what + " " +mH.codeToString(what)+ ":" + arg1 + "/" +obj);Message msg=Message.obtain();msg.what=what;msg.obj=obj;msg.arg1=arg1;msg.arg2=arg2;if (async) {msg.setAsynchronous(true);}mH.sendMessage(msg);}

View Code

这里mH指的是H,它是ActivityThread的内部类并继承Handler,是应用程序进程中主线程的消息管理类。H的代码如下所示。

private classH extends Handler {public static final int LAUNCH_ACTIVITY         = 100;public static final int PAUSE_ACTIVITY          = 101;
...public voidhandleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling:" +codeToString(msg.what));switch(msg.what) {caseLAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"activityStart");final ActivityClientRecord r= (ActivityClientRecord) msg.obj;//1r.packageInfo =getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);//2handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//3
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}break;caseRELAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"activityRestart");ActivityClientRecord r=(ActivityClientRecord)msg.obj;handleRelaunchActivity(r);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}break;...
}

View Code

查看H的handleMessage方法中对LAUNCH_ACTIVITY的处理,在注释1处将传过来的msg的成员变量obj转换为ActivityClientRecord。
在注释2处通过getPackageInfoNoCheck方法获得LoadedApk类型的对象并赋值给ActivityClientRecord 的成员变量packageInfo 。应用程序进程要启动Activity时需要将该Activity所属的APK加载进来,而LoadedApk就是用来描述已加载的APK文件。
在注释3处调用handleLaunchActivity方法,代码如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

private voidhandleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {...WindowManagerGlobal.initialize();//启动ActivityActivity a = performLaunchActivity(r, customIntent);//1if (a != null) {r.createdConfig= newConfiguration(mConfiguration);reportSizeConfigurations(r);Bundle oldState=r.state;//将Activity的状态置为ResumehandleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//2if (!r.activity.mFinished &&r.startsNotResumed) {performPauseActivityIfNeeded(r, reason);if(r.isPreHoneycomb()) {r.state=oldState;}}}else{try{//停止Activity启动
ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED,null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);}catch(RemoteException ex) {throwex.rethrowFromSystemServer();}}
}

View Code

注释1处的performLaunchActivity方法用来启动Activity ,注释2处的代码用来将Activity 的状态置为Resume。如果该Activity为null则会通知AMS停止启动Activity。来查看performLaunchActivity方法做了什么:
frameworks/base/core/java/android/app/ActivityThread.java

privateActivity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {//获取ActivityInfo类ActivityInfo aInfo = r.activityInfo;//1if (r.packageInfo == null) {//获取APK文件的描述类LoadedApkr.packageInfo =getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);//2
}ComponentName component= r.intent.getComponent();//3
...//创建要启动Activity的上下文环境ContextImpl appContext = createBaseContextForActivity(r);//4Activity activity = null;try{java.lang.ClassLoader cl=appContext.getClassLoader();//用类加载器来创建该Activity的实例activity =mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//5
...}catch(Exception e) {...}try{//创建ApplicationApplication app = r.packageInfo.makeApplication(false, mInstrumentation);//6
...if (activity != null) {.../***7 初始化Activity*/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);...if(r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//8} else{mInstrumentation.callActivityOnCreate(activity, r.state);}...}r.paused= true;mActivities.put(r.token, r);}catch(SuperNotCalledException e) {throwe;}catch(Exception e) {...}returnactivity;}

View Code

注释1处用来获取ActivityInfo,ActivityInfo用于存储代码和AndroidManifes设置的Activity和receiver节点信息,比如Activity的theme和launchMode。在注释2处获取APK文件的描述类LoadedApk。注释3处获取要启动的Activity的ComponentName类,ComponentName类中保存了该Activity的包名和类名。注释4处用来创建要启动Activity的上下文环境。注释5处根据ComponentName中存储的Activity类名,用类加载器来创建该Activity的实例。注释6处用来创建Application,makeApplication方法内部会调用Application的onCreate方法。注释7处调用Activity的attach方法初始化Activity,attach方法中会创建Window对象(PhoneWindow)并与Activity自身进行关联。注释8处会调用Instrumentation的callActivityOnCreate方法来启动Activity,如下所示。
frameworks/base/core/java/android/app/Instrumentation.java

public voidcallActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {prePerformCreate(activity);activity.performCreate(icicle, persistentState);//1
postPerformCreate(activity);}

View Code

注释1处调用了Activity的performCreate方法,代码如下所示。
frameworks/base/core/java/android/app/Activity.java

final voidperformCreate(Bundle icicle, PersistableBundle persistentState) {restoreHasCurrentPermissionRequest(icicle);onCreate(icicle, persistentState);mActivityTransitionState.readState(icicle);performCreateCommon();}

View Code

performCreate方法中会调用Activity的onCreate方法,讲到这里,根Activity就启动了,即应用程序就启动了。
根Activity启动过程就讲到这里,下面我们来学习根Activity启动过程中涉及到的进程。

2. 根Activity启动过程中涉及的进程

在应用程序进程没有创建的情况下,根Activity启动过程中会涉及到4个进程,分别是Zygote进程、Launcher进程、AMS所在进程(SyetemServer进程)、应用程序进程。它们之间的关系如下图所示。

首先Launcher进程向AMS请求创建根Activity,AMS会判断根Activity所需的应用程序进程是否存在并启动,如果不存在就会请求Zygote进程创建应用程序进程。应用程序进程准备就绪后会通知AMS,AMS会请求应用程序进程创建根Activity。上图中步骤2采用的是Socket通信,步骤1和步骤4采用的是Binder通信。
上图可能并不是很直观,为了更好的理解,下面给出这四个进程调用的时序图。

4.6.png4.6.png

如果是普通Activity启动过程会涉及到几个进程呢?答案是两个,AMS所在进程和应用程序进程。实际上理解了根Activity的启动过程(根Activity的onCreate过程),根Activity和普通Activity其他生命周期状态比如onStart、onResume等过程也会很轻松的掌握,这些知识点都是触类旁通的,想要具体了解这些知识点的同学可以自行阅读源码。

Android深入四大组件(五)Android8.0 根Activity启动过程(后篇)相关推荐

  1. Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)

    相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启 ...

  2. Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)

    相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启 ...

  3. WINCE6.0 + S3C2443的启动过程---nboot篇

    WINCE6.0 + S3C2443的启动过程---nboot篇 我们启动WINCE6.0的方式是:nboot+eboot+NK.那么是如何启动WINCE6.0系统映像的呢?首先是nboot把eboo ...

  4. service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;

    作者:DeepCoder 核心源码 关键类路径 Service 的启动过程相对 Activity 的启动过程来说简单了很多,我们都知道怎么去创建和启动一个 Service, 那么你有没有从源码角度研究 ...

  5. Android深入四大组件(八)广播的注册、发送和接收过程

    前言 我们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册.接收和发送过程.建议阅读此文前请先阅读Android深入理解四大组件系列的文章,知识重复的部分, ...

  6. Android进阶——Android四大组件启动机制之Activity启动过程

    前言 Activity启动过程涉及到的比较多的知识点有Binder的跨进程通讯,建议先看完Binder的跨进程通讯再来阅读本篇文章,在文章阅读开始,我们先要理解Activity启动模型,再者去理解有关 ...

  7. Android 之 四大组件、六大布局、五大存储

    Android 之四大组件.六大布局.五大存储:https://blog.csdn.net/shenggaofei/article/details/52450668 Android 四大组件.五大存储 ...

  8. Android基础——四大组件之Activity

    这几天继续回顾了一些Android基础方面的知识,今天跟大家一起回顾下Android四大组件中的Activity.虽然很基础,但工欲善其事,必先利其器.我们只有打好夯实的基础,才能在技术开发这条道路上 ...

  9. 【Android】四大组件之 ContentProvider

    前言 ContentProvider 是 Android 的四大组件之一,有时候我们需要操作其他应用程序的一些数据,就会用到 ContentProvider,ContentProvider 本质上是一 ...

最新文章

  1. vim编辑器操作命令大全-绝对全
  2. 未来,仅凭几个前端工程师,就能 hold 住一家企业吗?
  3. echars 在vue v-if 切换会 显示不出来或者显示出来但是不是百分百显示
  4. Android HTTP POST上传
  5. 反射setaccessible_advancedday16类加载器,反射
  6. MyBatis的配置和用法
  7. Exchange2003不能自动删除日志
  8. java高级语法_JAVA高级工程师课程笔记整理——(三)面向对象详解
  9. 全面质量管理体系方案
  10. 推荐:dhtmlx系列js工具包
  11. vins-mono--视觉跟踪--feature_trackers
  12. 计算机冯诺依曼原理及应用,冯·诺依曼计算机工作原理的核心是( )和“程序控制...
  13. 双色球历史数据下载最新2003年2021年
  14. C语言:求不确定科目数的加权平均分
  15. OpenStack Cinder特性之Volume-backed image介绍与验证
  16. win10浏览器加载很慢_解决Win10 Edge浏览器打开网页慢的问题
  17. 计算机基本原理 学习笔记(八)
  18. python库01—scipy.linalg(线性代数)
  19. 召唤出DirectX诊断工具
  20. matlab偏微分图像修复,图像修复 Region filling and object removal by exemplar-based image inpainting matlab实现...

热门文章

  1. [Python] L1-005. 考试座位号-PAT团体程序设计天梯赛GPLT
  2. android 应用搬家 分区,把安装在SD卡的应用存在DATA分区的数据移到SD卡上
  3. 一致 先验分布 后验分布_「分布式技术」分布式事务最终一致性解决方案,下篇...
  4. 判断用户 小程序_解读微信小程序用户运营四部曲
  5. 通过MBean server监控weblogic应用
  6. 多线程下单例模式:懒加载(延迟加载)和即时加载
  7. js如何获取window.location.href跳转后查询字符串的值?
  8. 012 基于以太访的本地文件hash存储查找Dapp实例(合约安装部署)
  9. 摩托罗拉MT788刷机
  10. Java网络连接之HttpURLConnection、HttpsURLConnection