ActivityThread运行框架

在分析中,我们可以看到真正对应应用进程的不是Application而是ActivityThread。我们从实际的应用堆栈可以看到:

NaiveStart.main()

ZygoteInit.main

ZygoteInit$MethodAndArgsCall.run

Method.Invoke

method.invokeNative

ActivityThread.main()

Looper.loop()

....

每个应用程序都以ActivityThread.main()为入口进入到消息循环处理。对于一个进程来讲,我们需要这个闭合的处理框架。

image

ActivitiyThread是应用程序概念空间的重要概念,他建立了应用进程运行的框架,并提供了一个IActivityThread接口作为与Activity Manager Service的通讯接口.通过该接口AMS可以将Activity的状态变化传递到客户端的Activity对象。

以前一直都说Activity的人口是onCreate方法。其实android上一个应用的入口,应该是ActivityThread。和普通的java类一样,入口是一个main方法。

public static final void main(String[] args) {
        SamplingProfilerIntegration.start();
       ……
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
       ……
        Looper.loop();
       ……
        thread.detach();
        ……
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }

下面仔细分析一下这个main方法。

2.Looper.prepareMainLooper();

ActivityThread其实就是我们经常说的UI thread,也就是主线程。我们都知道主线程可以使用Handler进行异步通信,因为主线程中已经创建了Looper,而这个Looper就是在这里创建的。如果其他线程需要使用Handler通信,就要自己去创建Looper。

3. sMainThreadHandler = new Handler();

创建一个Handler。

4. ActivityThread thread = new ActivityThread();

创建ActivityThread 对象。

ActivityThread 有几个比较重要的成员变量,会在创建ActivityThread对象时初始化。

(1)final ApplicationThread mAppThread = new ApplicationThread();

ApplicationThread继承自ApplicationThreadNative, 而ApplicationThreadNative又继承自Binder并实现了IApplicationThread接口。IApplicationThread继承自IInterface。这是一个很明显的binder结构,用于于Ams通信。IApplicationThread接口定义了对一个程序(linux的进程)操作的接口。ApplicationThread通过binder与Ams通信,并将Ams的调用,通过下面的H类(也就是Hnalder)将消息发送到消息队列,然后进行相应的操作,入activity的start, stop。

(2)final H mH = new H();

private final class H extends Handler

mH负责处理ApplicationThread发送到消息队列的消息,例如:

public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo);
                    handleLaunchActivity(r, null);
                } break;

5. handleLaunchActivity(r, null);

从名字中就可以看出,这里就将进行启动activity的工作了。

方法中主要调用了这一句:

Activity a = performLaunchActivity(r, customIntent);

6. performLaunchActivity()

进行了一些初始化和赋值操作后,创建activity。

activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);

然后调用:

mInstrumentation.callActivityOnCreate(activity, r.state);

这一句就会调用到acitivity的onCreate方法了,就进入了大多数应用开发的入口了。

在阅读SDK文档和研究Activity这个概念时,我感觉到了Android中若隐若现的Android自由无边界这个设计意图Android的应用只是一个虚的概念,并没有实际的入口,这个不像Window平台上的应用程序的概念,Android更多的是提供组件(Components)的概念。为什么要虚化应用的概念?我想这个虚化就是自由无边界设计意图的直接体现。突出请求和服务,突出组件个体,弱化边界,系统的各个组件可以自由的无边界的交流,服务请求者直接发出请求,不论这个对象在何处和属于谁的,组件是自由独立的个体,一个应用程序可以直接请求使用其他的应用的的组件,这个是Android应用框架设计的核心理念,其他的一切都是在为这个核心理念服务。

让程序员忽略应用的概念,甚至彻底的抛弃进程这样的概念,程序员看到的就是一个一个的组件,应用程序员利用这些组件来架构成一个所谓的应用,那么设计者首先要考虑的是什么呢?我想应该是一个抽象的应用模型,在这个模型下产生概念和接口。

Android则是彻底的组件化思想构建,一开始的应用程序概念就是ActivityService,Broadcast receiversContentProvider,IntentTask。这些概念体现了一个人机交互的模型本质:

界面呈现

发起请求,响应请求

内容交互

消息接收处理

ActivityAndroid应用的核心概念,简而言之Activity为用户交互管理者,有一个可视界面呈现,而ServiceActivity的区别是他在后台运行,没有界面呈现。而Intent的意义是意图,他在Android的概念空间中,代表消息,这个消息代表了请求的意图。

Activity可以到处存在,提供服务,消除空间差别,Activity是一个独立的个体,更能表现面向对象的实质。这个个体需要接受另外的个体的消息,可以随时发起对另外一个个体的请求。个体是自由的,Android中你可以开始一个Activity,但是没有权利消灭一个Activity,这是个体权利的体现,个体的消灭是由系统决定的,这个就是AndroidActivity蕴含的人文意义。

ActivityThread:

ActivityThread主要用来启动应用程序的主线程,并且管理在应用端跟用户打交道的activity。在应用端的activity信息全部被存储在ActivityThread的成员变量mActivities中。

final HashMap<IBinder, ActivityRecord> mActivities= new  HashMap<IBinder, ActivityRecord>();

也就是说,在mActivities中,记录了应用程序创建的所有activity实例记录,对应的是ActivityRecord

ActivityThread是怎么启动应用程序的呢?ActivityThread中有一个main函数,在这个里面,将启动应用程序并建立消息循环。在之前也介绍过,系统会为主线程自动创建消息循环。


每个应用程序对应着一个ActivityThread实例,应用程序由ActivityThread.main打开消息循环。每个应用程序同时也对应着一个ApplicationThread对象。该对象是activityThreadActivityManagerService之间的桥梁。

attach中还做了一件事情,就是通过代理调用attachApplication,并利用bindertransact机制,在ActivityManagerService中建立了ProcessRecord信息。

ActivityManagerService和ActivityStack位于同一个进程中,而ApplicationThread和ActivityThread位于另一个进程中,这个就要看代码,后面有两篇文章可以参考:《Android应用程序进程启动过程的源代码分析》和《Android系统进程Zygote启动过程的源代码分析》。
Zygote进程启动System进程->System进程创建一个线程来启动ActivityManagerService->ActivityManagerService内部又会创建一个ActivityStack来维护系统的Activity组件堆栈。
ActivityManagerService请求Zygote进程创建一个应用程序进程->应用程序进程加载一个ActivityThread实例->ActivityThread实例在内部创建一个ApplicationThread实例,用来和ActivityManagerService通信。

客户端保存的Activities是ActivityRecord的形式,是放在ActivityThread的mAcitivities中的,一个应用一个ActivityThead.
ActivityStack::realStartActivityLocked()
->app.thread.scheduleLaunchActivity() --- ProcessRecord.IApplicationThread::scheduleL...
->ApplicationThread::scheduleLaunchActivity()
->ActivityThread::handleMessage() case LAUNCH_ACTIVITY
->ActivityThread::handleLaunchActivity(r, null)
->ActivityThread::performLaunchActivity() --- mActivities.put(r.token, r);
服务端
AMS::startHomeActivityLocked()
->ActivityStack::startActivityLocked() --- mHistory.add(addPos, r);


  1. 在客户端和服务端分别有一个管理activity的地方,服务端是在mHistory中,处于mHistory栈顶的就是当前处于running状态的activity,客户端是在mActivities中。
  2. startActivity时,首先会在ActivityManagerService中建立HistoryRecord,并加入到mHistory中,然后通过scheduleLaunchActivity在客户端创建ActivityRecord记录并加入到mActivities中。最终在ActivityThread发起请求,进入消息循环,完成activity的启动和窗口的管理等

1. ActivityThread功能

它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行activities、broadcasts和其它操作。

在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity、BroadcastReceiver、Service)都会在同一个进程(Process)里执行,且由此进程的【主线程】负责执行。

在Android系统中,如果有特别指定(通过android:process),也可以让特定组件在不同的进程中运行。无论组件在哪一个进程中运行,默认情况下,他们都由此进程的【主线程】负责执行。

【主线程】既要处理Activity组件的UI事件,又要处理Service后台服务工作,通常会忙不过来。为了解决此问题,主线程可以创建多个子线程来处理后台服务工作,而本身专心处理UI画面的事件。

【主线程】的主要责任:

• 快速处理UI事件。而且只有它才处理UI事件, 其它线程还不能存取UI画面上的对象(如TextView等),此时, 主线程就叫做UI线程。基本上,Android希望UI线程能根据用户的要求做出快速响应,如果UI线程花太多时间处理后台的工作,当UI事件发生时,让用户等待时间超过5秒而未处理,Android系统就会给用户显示ANR提示信息。

只有UI线程才能执行View派生类的onDraw()函数。

• 快速处理Broadcast消息。【主线程】除了处理UI事件之外,还要处理Broadcast消息。所以在BroadcastReceiver的onReceive()函数中,不宜占用太长的时间,否则导致【主线程】无法处理其它的Broadcast消息或UI事件。如果占用时间超过10秒, Android系统就会给用户显示ANR提示信息。

注意事项:

尽量避免让【主线程】执行耗时的操作,让它能快速处理UI事件和Broadcast消息。

BroadcastReceiver的子类都是无状态的,即每次启动时,才会创建其对象,然后调用它的onReceive()函数,当执行完onReceive()函数时,就立即删除此对象。由于每次调用其函数时,会重新创建一个新的对象,所以对象里的属性值,是无法让各函数所共享。

1.1 Thread与SurfaceView

View组件由UI线程(主线程)所执行。如果需要迅速更新UI画面或UI画图需要较长时间,则需要使用SurfaceView。它可由后台线程(background thread)来执行,而View只能由UI(主)线程执行。SurfaceView内有高效的rendering机制,可以让后台线程快速刷新Surface的内容。

View ---> UI(主)线程

SurfaceView ---> 后台线程

2. Android应用程序主线程stack

在一个只有Activity派生类的应用程序中,它包含如下线程:

main线程stack如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片

  1. at android.os.MessageQueue.nativePollOnce(Native Method)
  2. at android.os.MessageQueue.next(MessageQueue.java:118)
  3. at android.os.Looper.loop(Looper.java:118)
  4. at android.app.ActivityThread.main(ActivityThread.java:4424)// Java main入口函数
  5. at java.lang.reflect.Method.invokeNative(Native Method)
  6. at java.lang.reflect.Method.invoke(Method.java:511)
  7. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
  8. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
  9. at dalvik.system.NativeStart.main(Native Method)



JDWP线程stack如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片

  1. at org.apache.harmony.dalvik.ddmc.DdmVmInternal.getStackTraceById(Native Method)
  2. at android.ddm.DdmHandleThread.handleSTKL(DdmHandleThread.java:131)
  3. at android.ddm.DdmHandleThread.handleChunk(DdmHandleThread.java:77)
  4. at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
  5. at dalvik.system.NativeStart.run(Native Method)


3. IApplicationThread关系图

4. ActivityThread类

ActivityThread类即代表Application主线程。

4.1 类中关键信息

[java] view plaincopy在CODE上查看代码片派生到我的代码片

  1. /**
  2. * This manages the execution of the main thread in an
  3. * application process, scheduling and executing activities,
  4. * broadcasts, and other operations on it as the activity
  5. * manager requests.
  6. *
  7. * {@hide}
  8. */
  9. publicfinalclassActivityThread {
  10. staticContextImpl mSystemContext =null;
  11. staticIPackageManager sPackageManager;
  12. // 创建ApplicationThread实例,以接收AMS指令并执行
  13. finalApplicationThread mAppThread =newApplicationThread();
  14. finalLooper mLooper = Looper.myLooper();
  15. finalH mH =newH();
  16. finalHashMap<IBinder, ActivityClientRecord> mActivities
  17. newHashMap<IBinder, ActivityClientRecord>();
  18. // List of new activities (via ActivityRecord.nextIdle) that should
  19. // be reported when next we idle.
  20. ActivityClientRecord mNewActivities = null;
  21. // Number of activities that are currently visible on-screen.
  22. intmNumVisibleActivities =0;
  23. finalHashMap<IBinder, Service> mServices
  24. newHashMap<IBinder, Service>();
  25. Application mInitialApplication;
  26. finalArrayList<Application> mAllApplications
  27. newArrayList<Application>();
  28. staticfinalThreadLocal<ActivityThread> sThreadLocal =newThreadLocal<ActivityThread>();
  29. Instrumentation mInstrumentation;
  30. staticHandler sMainThreadHandler;// set once in main()
  31. staticfinalclassActivityClientRecord {
  32. IBinder token;
  33. intident;
  34. Intent intent;
  35. Bundle state;
  36. Activity activity;
  37. Window window;
  38. Activity parent;
  39. String embeddedID;
  40. Activity.NonConfigurationInstances lastNonConfigurationInstances;
  41. booleanpaused;
  42. booleanstopped;
  43. booleanhideForNow;
  44. Configuration newConfig;
  45. Configuration createdConfig;
  46. ActivityClientRecord nextIdle;
  47. String profileFile;
  48. ParcelFileDescriptor profileFd;
  49. booleanautoStopProfiler;
  50. ActivityInfo activityInfo;
  51. CompatibilityInfo compatInfo;
  52. LoadedApk packageInfo; //包信息,通过调用ActivityThread.getPapckageInfo而获得
  53. List<ResultInfo> pendingResults;
  54. List<Intent> pendingIntents;
  55. booleanstartsNotResumed;
  56. booleanisForward;
  57. intpendingConfigChanges;
  58. booleanonlyLocalRequest;
  59. View mPendingRemoveWindow;
  60. WindowManager mPendingRemoveWindowManager;
  61. ...
  62. }
  63. privateclassApplicationThreadextendsApplicationThreadNative {
  64. privatevoidupdatePendingConfiguration(Configuration config) {
  65. synchronized(mPackages) {
  66. if(mPendingConfiguration ==null||
  67. mPendingConfiguration.isOtherSeqNewer(config)) {
  68. mPendingConfiguration = config;
  69. }
  70. }
  71. }
  72. publicfinalvoidschedulePauseActivity(IBinder token,booleanfinished,
  73. booleanuserLeaving,intconfigChanges) {
  74. queueOrSendMessage(
  75. finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
  76. token,
  77. (userLeaving ? 1:0),
  78. configChanges);
  79. }
  80. // we use token to identify this activity without having to send the
  81. // activity itself back to the activity manager. (matters more with ipc)
  82. publicfinalvoidscheduleLaunchActivity(Intent intent, IBinder token,intident,
  83. ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
  84. Bundle state, List<ResultInfo> pendingResults,
  85. List<Intent> pendingNewIntents, booleannotResumed,booleanisForward,
  86. String profileName, ParcelFileDescriptor profileFd, booleanautoStopProfiler) {
  87. ActivityClientRecord r = newActivityClientRecord();
  88. r.token = token;
  89. r.ident = ident;
  90. r.intent = intent;
  91. r.activityInfo = info;
  92. r.compatInfo = compatInfo;
  93. r.state = state;
  94. r.pendingResults = pendingResults;
  95. r.pendingIntents = pendingNewIntents;
  96. r.startsNotResumed = notResumed;
  97. r.isForward = isForward;
  98. r.profileFile = profileName;
  99. r.profileFd = profileFd;
  100. r.autoStopProfiler = autoStopProfiler;
  101. updatePendingConfiguration(curConfig);
  102. queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
  103. }
  104. ...
  105. }
  106. privateclassHextendsHandler {
  107. publicvoidhandleMessage(Message msg) {
  108. if(DEBUG_MESSAGES) Slog.v(TAG,">>> handling: "+ codeToString(msg.what));
  109. switch(msg.what) {
  110. caseLAUNCH_ACTIVITY: {
  111. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
  112. ActivityClientRecord r = (ActivityClientRecord)msg.obj;
  113. r.packageInfo = getPackageInfoNoCheck(
  114. r.activityInfo.applicationInfo, r.compatInfo);
  115. handleLaunchActivity(r, null);
  116. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  117. break;
  118. ...
  119. }
  120. if(DEBUG_MESSAGES) Slog.v(TAG,"<<< done: "+ codeToString(msg.what));
  121. }
  122. ...
  123. }
  124. publicstaticActivityThread currentActivityThread() {
  125. returnsThreadLocal.get();
  126. }
  127. publicstaticvoidmain(String[] args) {
  128. SamplingProfilerIntegration.start();
  129. // CloseGuard defaults to true and can be quite spammy.  We
  130. // disable it here, but selectively enable it later (via
  131. // StrictMode) on debug builds, but using DropBox, not logs.
  132. CloseGuard.setEnabled(false);
  133. Environment.initForCurrentUser();
  134. // Set the reporter for event logging in libcore
  135. EventLogger.setReporter(newEventLoggingReporter());
  136. Process.setArgV0("<pre-initialized>");
  137. Looper.prepareMainLooper();
  138. // 创建ActivityThread实例
  139. ActivityThread thread = newActivityThread();
  140. thread.attach(false);
  141. if(sMainThreadHandler ==null) {
  142. sMainThreadHandler = thread.getHandler();
  143. }
  144. AsyncTask.init();
  145. if(false) {
  146. Looper.myLooper().setMessageLogging(new
  147. LogPrinter(Log.DEBUG, "ActivityThread"));
  148. }
  149. Looper.loop();
  150. thrownewRuntimeException("Main thread loop unexpectedly exited");
  151. }
  152. }




4.2 家族图谱

4.3 ActivityThread内部类

4.4 ActivityThread工作流程

ActivityThread相关推荐

  1. 【Android】 01. APP 进程启动和 ActivityThread 的关系

    2019独角兽企业重金招聘Python工程师标准>>> 首先我们应该知道2个概念: 我们应该知道在Android中一个app就是一个进程: 我们在普通的Java程序中一个程序的入口是 ...

  2. Android Hook ActivityThread mH 消息

    背景: 今天面试被问到如何监听ActivityThread mH 类的消息,当时的想法是,mH 其实就是Handler, Android 没有提供获取到mH 的方法,就算我可以拿到mH 的 Loope ...

  3. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 二 )

    文章目录 前言 一.ActivityManagerService.attachApplicationLocked 二.ActivityStackSupervisor.attachApplication ...

  4. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 一 )

    文章目录 一.ActivityThread 主函数启动 二.ActivityThread 绑定 ApplicationThread 三.AMS attachApplication -> atta ...

  5. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )

    文章目录 前言 一.ActivityThread 类 handleLaunchActivity -> performLaunchActivity 方法 二.Instrumentation.new ...

  6. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )

    文章目录 前言 一.ClientTransactionHandler.scheduleTransaction 二.ActivityThread.H 处理 EXECUTE_TRANSACTION 消息 ...

  7. 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )

    文章目录 前言 一.热启动与冷启动选择 二.AMS 进程中执行的相关操作 三.通过 Binder 机制转到 ActivityThread 中执行的操作 总结 前言 上一篇博客 [Android 启动过 ...

  8. 【Android 安全】DEX 加密 ( Application 替换 | 分析 Activity 组件中获取的 Application | ActivityThread | LoadedApk )

    文章目录 一. Activity 中的 getApplication() 方法分析 二. ActivityThread 中的 H 处理 消息及 handleLaunchActivity 方法操作 三. ...

  9. 【Android 安全】DEX 加密 ( Application 替换 | ActivityThread 中的 mAllApplications 集合添加 Application )

    文章目录 一. 当前 Application 替换进度 二. ActivityThread 中的 mAllApplications 集合添加 Application 一. 当前 Application ...

  10. 【Android 安全】DEX 加密 ( Application 替换 | 获取 ContextImpl、ActivityThread、LoadedApk 类型对象 )

    文章目录 一.获取对象类型分析 二.替换 Application 时机 一.获取对象类型分析 在 [Android 安全]DEX 加密 ( Application 替换 | 获取 ContextImp ...

最新文章

  1. WM_PAINT消息小结
  2. 【前端酷站】分享一个纯 Javascript 的图表库与立体像素风制作~
  3. 将Html文档整理为规范XML文档
  4. 多线程(6)线程同步
  5. 批处理之坑爹的感叹号和变量延迟扩展
  6. 茶百科 android 论文,基于android平台手机茶百科开发_学位论文.doc
  7. CentOS7下的AIDE***检测配置
  8. C语言中字符串的处理方式(一)
  9. 运行control userpasswords2实现winXP自动登录
  10. 在struts中实现验证码
  11. 数据库mysql菜鸟教程_MySQL数据库菜鸟教程(一)
  12. AxureRP8.1(注册码)破解汉化教程
  13. Go语言的安装与环境配置
  14. LRU算法(有彩蛋)
  15. WEBVTT字幕格式转SRT
  16. Photoshop文字之——制作写在宣纸上的水彩字特效
  17. 收费的Chemdraw跟不上时代潮流
  18. lua入门之环境搭建、第一个demo
  19. unity3d:向量计算:获得两点连线的垂直向量,判断目标方位(前后左右)
  20. WPS使用,实现用WPS打开在线文档并且进行编辑

热门文章

  1. C++基础-ASCII码
  2. 怎么看计算机的网络配置信息,如何查看电脑的网络设置
  3. Navicat备份恢复数据表及表结构
  4. js浏览器内置对象和js内置对象
  5. 软件的知识产权保护---反不正当竞争法
  6. 数组类型参数传递问题:$.ajax传递数组的traditional参数传递必须true
  7. 无线振动传感器之利:实现设备远程监控和管理
  8. 晨心家政:数据库30条军规解读
  9. [MATLAB]一元线性回归(regress参数检验说明)
  10. 探秘文房四宝之毛笔的由来:大将蒙恬斩兔为笔