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如下:

  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如下:

  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 类中关键信息

  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. public final class ActivityThread {
  10. static ContextImpl mSystemContext = null;
  11. static IPackageManager sPackageManager;
  12. // 创建ApplicationThread实例,以接收AMS指令并执行
  13. final ApplicationThread mAppThread = new ApplicationThread();
  14. final Looper mLooper = Looper.myLooper();
  15. final H mH = new H();
  16. final HashMap<IBinder, ActivityClientRecord> mActivities
  17. = new HashMap<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. int mNumVisibleActivities = 0;
  23. final HashMap<IBinder, Service> mServices
  24. = new HashMap<IBinder, Service>();
  25. Application mInitialApplication;
  26. final ArrayList<Application> mAllApplications
  27. = new ArrayList<Application>();
  28. static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();
  29. Instrumentation mInstrumentation;
  30. static Handler sMainThreadHandler;  // set once in main()
  31. static final class ActivityClientRecord {
  32. IBinder token;
  33. int ident;
  34. Intent intent;
  35. Bundle state;
  36. Activity activity;
  37. Window window;
  38. Activity parent;
  39. String embeddedID;
  40. Activity.NonConfigurationInstances lastNonConfigurationInstances;
  41. boolean paused;
  42. boolean stopped;
  43. boolean hideForNow;
  44. Configuration newConfig;
  45. Configuration createdConfig;
  46. ActivityClientRecord nextIdle;
  47. String profileFile;
  48. ParcelFileDescriptor profileFd;
  49. boolean autoStopProfiler;
  50. ActivityInfo activityInfo;
  51. CompatibilityInfo compatInfo;
  52. LoadedApk packageInfo; //包信息,通过调用ActivityThread.getPapckageInfo而获得
  53. List<ResultInfo> pendingResults;
  54. List<Intent> pendingIntents;
  55. boolean startsNotResumed;
  56. boolean isForward;
  57. int pendingConfigChanges;
  58. boolean onlyLocalRequest;
  59. View mPendingRemoveWindow;
  60. WindowManager mPendingRemoveWindowManager;
  61. ...
  62. }
  63. private class ApplicationThread extends ApplicationThreadNative {
  64. private void updatePendingConfiguration(Configuration config) {
  65. synchronized (mPackages) {
  66. if (mPendingConfiguration == null ||
  67. mPendingConfiguration.isOtherSeqNewer(config)) {
  68. mPendingConfiguration = config;
  69. }
  70. }
  71. }
  72. public final void schedulePauseActivity(IBinder token, boolean finished,
  73. boolean userLeaving, int configChanges) {
  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. public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
  83. ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
  84. Bundle state, List<ResultInfo> pendingResults,
  85. List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
  86. String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
  87. ActivityClientRecord r = new ActivityClientRecord();
  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. private class H extends Handler {
  107. public void handleMessage(Message msg) {
  108. if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
  109. switch (msg.what) {
  110. case LAUNCH_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. public static ActivityThread currentActivityThread() {
  125. return sThreadLocal.get();
  126. }
  127. public static void main(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(new EventLoggingReporter());
  136. Process.setArgV0("<pre-initialized>");
  137. Looper.prepareMainLooper();
  138. // 创建ActivityThread实例
  139. ActivityThread thread = new ActivityThread();
  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. throw new RuntimeException("Main thread loop unexpectedly exited");
  151. }
  152. }

4.2 家族图谱

4.3 ActivityThread内部类

4.4 ActivityThread工作流程

Android ActivityThread(主线程或UI线程)简介的更多相关文章

  1. [Android学习笔记]子线程更新UI线程方法之Handler

    关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...

  2. 新建线程与UI线程间的通信

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  3. OkHttp3几个简单的例子和在子线程更新UI线程的方法

    okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...

  4. C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它

    C# 委托 / 跨线程访问UI /  线程间操作无效: 从不是创建控件“Form1”的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 using System; ...

  5. 主线程与UI线程简介

    ---------------siwuxie095                             Java 程序的主线程     当 Java 程序启动时,一个线程立刻运行,该线程通常叫做程 ...

  6. C#用副线程改主线程(UI线程)的控件属性的方法(包括Winform和WPF)

    C#用副线程去试图修改主线程的UI控件会报出异常,解决方案是使用副线程注册事件通知主线程自己去修改UI控件 在winform中,方法如下 private void button1_Click(obje ...

  7. Android开之在非UI线程中更新UI

    当在非UI线程中更新UI(程序界面)时会出现例如以下图所看到的的异常: 那怎样才干在非UI线程中更细UI呢? 方法有非常多种.在这里主要介绍三种: 第一种:调用主线程mHandler的post(Run ...

  8. C#中后台线程和UI线程的交互

    在C#中,从Main()方法开始一个默认的线程,一般称之为主线程,如果在这个进行一些非常耗CPU的计算,那么UI界面就会被挂起而处于假死状态,也就是说无法和用户进行交互了,特别是要用类似进度条来实时显 ...

  9. WPF线程获取UI线程

    WPF中只能是UI线程才可以改变UI控件相关,当采用多线程工作时,可用以下代码获取 UI线程进行操作: App.Current.Dispatcher.Invoke((Action)delegate() ...

随机推荐

  1. 为什么接口要规定成员变量必须是public static final的呢?(转)

    在interface里面的变量默认都是public static final 的.所以可以直接省略修饰符: String param="ssm"://变量需要初始化 为什么接口要规 ...

  2. SQL 中逻辑运算符的优先级

    三个逻辑运算符: NOT AND OR 它们的优先级依次降低(跟多数的高级程序设计语言的优先级顺序一致) 如果要提升某部分的优先级,可以使用半角括号实现 (这点也跟多数高级程序设计语言一致)

  3. zw版【转发·台湾nvp系列Delphi例程】HALCON FillUp2

    zw版[转发·台湾nvp系列Delphi例程]HALCON FillUp2 procedure TForm1.Button1Click(Sender: TObject);var op : HOpera ...

  4. ApkDec android反编译工具

    转自:http://www.newasp.net/soft/70498.html 下载 ApkDec是一款免费的绿色APK反编译工具 forandroid ,由android开发者社区开发. ApkD ...

  5. android 项目学习随笔十三(ListView实现ITEM点击事件,将已读状态持久化到本地)

    1.因为给LISTVIEW增加了两个头布局,所以在点击事件ITEM索引会增加2,比如原来第一条数据的索引应该为0,增加两个头布局后,它的索引变为        2,为了使LISTVIEW的ITEM在点 ...

  6. selenium 右键另存为操作

    from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsbrowse ...

  7. 为 Macbook 增加锁屏热键技巧

    第一步,找到“系统偏好设置”下的“安全性与隐私”,在“通用”页里勾上“进入睡眠或开始屏幕保护程序后立即要求输入密码”. 第二步,要用快捷键启动屏幕保护程序,相对复杂一点.在“应用程序”里找到“Auto ...

  8. 【python cookbook】【数据结构与算法】19.同时对数据做转换和换算

    问题:我们需要调用一个换算函数(例如sum().min().max()),但是首先需对数据做转换或者筛选处理 解决方案:非常优雅的方法---在函数参数中使用生成器表达式 例如: # 计算平方和 num ...

  9. 将edit ctrL弄的像个dos

    case WM_CTLCOLOREDIT: { HWND hShellText = GetDlgItem(hDlg,IDC_TXT_SHELL); if (hShellText == (HWND)lP ...

  10. windows cmd color setup

    设置颜色的话,一般可定会有foreground和background color设置:(其实color /?直接看一下就好了) Color Background Foreground Black 0 ...