专栏首页刘望舒Android深入四大组件(一)应用程序启动过程

Android深入四大组件(一)应用程序启动过程

前言

在此前的文章中,我讲过了Android系统启动流程和Android应用进程启动过程,这一篇顺理成章来学习Android 7.0的应用程序的启动过程。分析应用程序的启动过程其实就是分析根Activity的启动过程。

1.Launcher请求ActivityManageService

Android系统启动流程(四)Launcher启动过程与系统启动流程这篇文章我讲过Launcher启动后会将已安装应用程序的快捷图标显示到界面上,当我们点击应用程序的快捷图标时就会调用Launcher的startActivitySafely方法,如下所示。 packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

startActivitySafely函数中主要就是调用了startActivity函数: packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

在注释1处设置Flag为Intent.FLAG_ACTIVITY_NEW_TASK,这样根Activity会在新的任务栈中启动。在注释2处调用了startActivity函数: frameworks/base/core/java/android/app/Activity.java

startActivity会调用startActivityForResult函数,其中第二个参数为-1,表示Launcher不需要知道Activity启动的结果,startActivityForResult函数的代码如下所示。 frameworks/base/core/java/android/app/Activity.java

mParent是Activity类型的,表示当前Activity的父类。因为目前根Activity还没有创建出来,因此,mParent == null成立。接着调用Instrumentation的execStartActivity方法,Instrumentation主要用来监控应用程序和系统的交互,execStartActivity方法的代码如下所示。 frameworks/base/core/java/android/app/Instrumentation.java

首先会调用ActivityManagerNative的getDefault来获取ActivityManageService(以后简称为AMS)的代理对象,接着调用它的startActivity方法。首先我们先来查看ActivityManagerNative的getDefault方法做了什么: frameworks/base/core/java/android/app/ActivityManagerNative.java

getDefault方法调用了gDefault的get方法,我们接着往下看,gDefault 是一个Singleton类。注释1处得到名为"activity"的Service代理对象,也就是ActivityManagerService的代理对象。接着在注释2处将它封装成ActivityManagerProxy(以后简称为AMP)类型对象,并将它保存到gDefault中,此后调用ActivityManagerNative的getDefault方法就会直接获得AMS的代理AMP对象。 回到Instrumentation类的execStartActivity方法中,从上面得知就是调用AMP的startActivity,其中AMP是ActivityManagerNative的内部类,代码如下所示。 frameworks/base/core/java/android/app/ActivityManagerNative.java

首先会将传入的参数写入到Parcel类型的data中。在注释1处通过IBinder对象mRemote想AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,最终会调用ActivityManagerNative的onTransact方法中执行,如下所示。 frameworks/base/core/java/android/app/ActivityManagerNative.java

onTransact中会调用AMS的startActivity方法,如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

为了便于理解,给出Launcher到AMS调用过程的时序图。

2.ActivityManageService到ApplicationThread的调用流程

AMS的startActivity方法中return了startActivityAsUser方法: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

startActivityAsUser方法中又return了mActivityStarter的startActivityMayWait方法,代码如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

又调用了startActivityLocked方法,代码如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

startActivityLocked函数代码非常多,我们只需要关注doPendingActivityLaunchesLocked方法,代码如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

接着又调用startActivityUnchecked方法: frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

startActivityUnchecked方法中调用了ActivityStackSupervisor类型的mSupervisor的resumeFocusedStackTopActivityLocked方法,如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

在注释1处又调用了ActivityStack类型mFocusedStack的resumeTopActivityUncheckedLocked方法: frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

紧接着查看ActivityStack的resumeTopActivityInnerLocked方法: frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

resumeTopActivityInnerLocked方法代码非常多,我们只需要关注调用了ActivityStackSupervisor类型mStackSupervisor的startSpecificActivityLocked方法,代码如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

在注释1处如果当前Activity所在的Application运行的话,会执行注释2处的代码。realStartActivityLocked方法的代码如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

这里的 app.thread指的是IApplicationThread,它的实现是ActivityThread的内部类ApplicationThread,其中ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative继承了Binder并实现了IApplicationThread接口。 讲到这里再给出ActivityManageService到ApplicationThread调用过程的时序图,如下图所示。

3.ActivityThread启动Activity

Android应用程序进程启动过程(前篇)这篇文章中提到过ActivityThread,在应用程序进程启动时会创建ActivityThread实例。ActivityThread作为应用程序进程的核心类,它是如何启动应用程序(Activity)的呢?我们接着往下看。 根据上文接着查看ApplicationThread的scheduleLaunchActivity方法,代码如下所示。 frameworks/base/core/java/android/app/ActivityThread.java

scheduleLaunchActivity方法会将启动Activity的参数封装成ActivityClientRecord ,再将ActivityClientRecord通过sendMessage方法向应用进程的主线程发送类型为LAUNCH_ACTIVITY的消息,sendMessage方法的代码如下所示。

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

这里mH指的是H,它是ActivityThread的内部类并继承Handler,H的代码如下所示。

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

查看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

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

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

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

performCreate方法中会调用Activity的onCreate方法,这样Activity就启动了,即应用程序就启动了。 应用程序启动过程就讲到这里,最后附上ActivityThread启动Activity的时序图。

本文分享自微信公众号 - 刘望舒(liuwangshuAndroid),作者:刘望舒

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-04-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android解析WindowManager(三)Window的添加过程

    前言 在此前的系列文章中我们学习了WindowManager体系和Window的属性,这一篇我们接着来讲Window的添加过程。建议阅读此篇文章前先阅读本系列的...

    用户1269200
  • Android深入四大组件(四)广播的注册、发送和接收过程

    前言 我们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册、接收和发送过程。建议阅读此文前请先阅读Android深入...

    用户1269200
  • Android应用程序进程启动过程(后篇)

    前言 在前篇中我们讲到了Android应用程序进程启动过程,这一篇我们来讲遗留的知识点:在应用程序进程创建过程中会启动Binder线程池以及在应用程序进程启动后...

    用户1269200
  • mysql学习笔记(七)事务&批处理和JDBC的使用爬坑

    一个事务执行多个操作时,要么所有事务被提交,对数据库的操作成功。要么中途出现问题或者反悔回滚

    逆回十六夜
  • troubleshoot之:用control+break解决线程死锁问题

    写过java多线程程序的人应该都知道,多线程中一个很重要的事情就是状态的同步,但是在状态同步的过程中,一不小心就有可能会导致死锁的问题。

    程序那些事
  • R语言随机森林模型中具有相关特征的变量重要性

    变量重要性图是查看模型中哪些变量有趣的好工具。由于我们通常在随机森林中使用它,因此它看起来非常适合非常大的数据集。大型数据集的问题在于许多特征是“相关的”,在这...

    拓端
  • R语言随机森林模型中具有相关特征的变量重要性

    变量重要性图是查看模型中哪些变量有趣的好工具。由于我们通常在随机森林中使用它,因此它看起来非常适合非常大的数据集。大型数据集的问题在于许多特征是“相关的”,在这...

    拓端
  • 【面试现场】如何实现可以获取最小值的栈?

    题目:我现在需要实现一个栈,这个栈除了可以进行普通的push、pop操作以外,还可以进行getMin的操作,getMin方法被调用后,会返回当前栈的最小值,你会...

    乔戈里
  • 【面试现场】如何实现可以获取最小值的栈?

    该公号有个「面试现场」的专题,感觉写的很不错,看了挺有收获,特地转载一篇过来给大伙,希望你们也能有所收获。如果喜欢的话,可以关注该公号呢----「互联网侦察」。...

    帅地
  • 手把手教你写《雷神》游戏(一)

    提莫队长

扫码关注云+社区

领取腾讯云代金券