当前位置:   article > 正文

Android系统中Thread,Looper,MessageQueue,Message,Handler相互关系的简单分析_android server new thread looper handlemessage

android server new thread looper handlemessage
先粗略说一下Thread,Looper,MessageQueue,Message,Handler之间的基本关系:
1.一个Thread实例中会包含一个Looper实例
2.一个Looper实例中会包含一个MessageQueue实例
3.Handler把Message推送到MessageQueue内
4.Looper实例在Thread中处于死循环运行状态,负责不断的从MessageQueue中取出消息,取出消息后交给Handler处理
小结:Looper是运行在Thread实例中的,Message又是由Looper取出来交给Handler处理的,所以Handler处理Message的地方也是运行在Thread实例中的。

这个Thread实例有可能是UI主线程,也有可能是自定义线程 :)


Android开发中Handler处理Message分两种情况:
1.Handler在应用主线程中处理Message
2.Handler在自建的线程中处理Message


对于第1种情况先按下不表,等分析完第2种情况后再回过头来看第1种情况会容易很多。
对于第2种情况,开发情景一般如下面例子的代码,先上全部代码:

  1. // 自定义类ExampleThread继承自Thread,内部Handler成员internalHandler
  2. class ExampleThread extends Thread {
  3. private static final String TAG = "ExampleThread";
  4. private static final int MSG_WORK = 1;
  5. private static final int MSG_PLAY_GAMES = 2;
  6. private Handler internalHandler;
  7. @Override
  8. public void run() {
  9. Looper.prepare();
  10. synchronized (ExampleThread.this) {
  11. internalHandler = new Handler() {
  12. @Override
  13. public void handleMessage(Message msg) {
  14. switch (msg.what) {
  15. case MSG_WORK:
  16. Log.d(TAG, "I'm working");
  17. break;
  18. case MSG_PLAY_GAMES:
  19. Log.d(TAG, "I'm playing games");
  20. break;
  21. default:
  22. break;
  23. }
  24. }
  25. };
  26. ExampleThread.this.notifyAll();
  27. }
  28. Looper.loop();
  29. }
  30. public void goWork() {
  31. while (internalHandler == null) {
  32. try {
  33. wait();
  34. } catch (InterruptedException e) {
  35. Thread.currentThread().interrupt();
  36. }
  37. }
  38. internalHandler.sendEmptyMessage(MSG_WORK);
  39. }
  40. public void goPlayGames() {
  41. while (internalHandler == null) {
  42. try {
  43. wait();
  44. } catch (InterruptedException e) {
  45. Thread.currentThread().interrupt();
  46. }
  47. }
  48. Message msg = Message.obtain(internalHandler, MSG_PLAY_GAMES);
  49. msg.sendToTarget();
  50. }
  51. }
  52. // 测试代码,goWork和goPlayGames方法的实现都是通过internalHandler发送Message,internalHandler是在exampleThread线程内部处理Message
  53. public void test() {
  54. ExampleThread exampleThread = new ExampleThread();
  55. exampleThread.start();
  56. exampleThread.goWork();
  57. exampleThread.goPlayGames();
  58. }

从ExampleThread.run中只看到了下面3步:
Looper.prepare();
internalHandler = new Handler()
Looper.loop();
难道只要这3步就把Handler处理Message的流程机制创建好了?


那我们只能一步步来分析了。

先看Looper.prepare();做了些是什么,上Looper的关键源码:

  1. package android.os;
  2. public final class Looper {
  3. private static final String TAG = "Looper";
  4. /*ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量*/
  5. static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
  6. /*当所在线程为UI主线程时sMainLooper才会被使用到*/
  7. private static Looper sMainLooper;
  8. /*Looper持有的消息队列*/
  9. final MessageQueue mQueue;
  10. /*Looper所在线程的实例*/
  11. final Thread mThread;
  12. /*自定义线程调用此方法来prepare*/
  13. public static void prepare() {
  14. prepare(true);
  15. }
  16. private static void prepare(boolean quitAllowed) {
  17. /*如果sThreadLocal.get()不为null,则表示Looper已经prepare过了,不能重复prepare*/
  18. if (sThreadLocal.get() != null) {
  19. throw new RuntimeException("Only one Looper may be created per thread");
  20. }
  21. /*调用Looper构造器创建一个Looper实例,并set进sThreadLocal。由于ThreadLocal的特性,在同一线程(当前线程)中我们通过sThreadLocal.get()得到的都是同一个Looper实例;而在不同线程中我们通过sThreadLocal.get()得到的又是不同的Looper实例。*/
  22. sThreadLocal.set(new Looper(quitAllowed));
  23. }
  24. private Looper(boolean quitAllowed) {
  25. /*创建一个消息队列*/
  26. mQueue = new MessageQueue(quitAllowed);
  27. /*获得当前线程的实例*/
  28. mThread = Thread.currentThread();
  29. }
  30. /*UI主线程调用此方法来prepare*/
  31. public static void prepareMainLooper() {
  32. /*也是通过调用prepare来创建Looper实例*/
  33. prepare(false);
  34. synchronized (Looper.class) {
  35. if (sMainLooper != null) {
  36. throw new IllegalStateException("The main Looper has already been prepared.");
  37. }
  38. /*跟自定义线程不同的是把创建的Loooper实例赋给了sMainLooper引用*/
  39. sMainLooper = myLooper();
  40. }
  41. }
  42. /*其他进程要跟UI主线程IPC的话可以通过此方法获得主线程的Looper,然后向主线程发送事件,比如按键事件等*/
  43. public static Looper getMainLooper() {
  44. synchronized (Looper.class) {
  45. return sMainLooper;
  46. }
  47. }
  48. /*Looper开始工作*/
  49. public static void loop() {
  50. final Looper me = myLooper();
  51. if (me == null) {
  52. throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
  53. }
  54. /*当前Looper持有的消息队列*/
  55. final MessageQueue queue = me.mQueue;
  56. for (;;) {
  57. /*从消息队列中取出下一条Message,可能会阻塞*/
  58. Message msg = queue.next();
  59. if (msg == null) {
  60. /*表示消息队列正在quitting*/
  61. return;
  62. }
  63. /*取出来的Message交给target(即Handler,为什么target是Handler等后面Message源码部分再说)去调度处理*/
  64. msg.target.dispatchMessage(msg);
  65. /*Message处理完后释放资源*/
  66. msg.recycleUnchecked();
  67. }
  68. }
  69. /*prepare时把创建的Looper实例set进了sThreadLocal,所以在同一线程中myLooper方法得到的肯定是同一个Looper实例,所以一个Thread实例只有一个Looper实例*/
  70. public static @Nullable Looper myLooper() {
  71. return sThreadLocal.get();
  72. }
  73. /*在Looper的构造器中创建了MessageQueue,由myLooper()性质决定了同一线程中myQueue方法得到的肯定也是同一个MessageQueue实例*/
  74. public static @NonNull MessageQueue myQueue() {
  75. return myLooper().mQueue;
  76. }
  77. /*判断是否在当前线程中。比如在线程A的代码中aLooper = myLooper()来获得线程A的Looper实例aLooper,然后可能在任何代码地方通过aLooper.isCurrentThread()来判断所在代码是否运行在线程A中*/
  78. public boolean isCurrentThread() {
  79. return Thread.currentThread() == mThread;
  80. }
  81. /*退出消息队列,当前消息队列中未被处理的消息将被丢弃。一旦调用quit后再向消息队列中推送消息就会失败,例如Handler.sendMessage(Message)会返回false*/
  82. public void quit() {
  83. mQueue.quit(false);
  84. }
  85. /*安全退出消息队列,当前消息队列中的消息都会被处理完。同样,一旦调用quit后再向消息队列中推送消息就会失败,例如Handler.sendMessage(Message)会返回false*/
  86. public void quitSafely() {
  87. mQueue.quit(true);
  88. }
  89. /*获得Looper实例中的当前线程实例*/
  90. public @NonNull Thread getThread() {
  91. return mThread;
  92. }
  93. /*获得Looper实例持有的消息队列,此方法为非静态方法,myQueue()为静态方法*/
  94. public @NonNull MessageQueue getQueue() {
  95. return mQueue;
  96. }
  97. }

通过Looper的源码可以明白,通过调用Looper.prepare(),已经在当前Thread中创建了一个唯一的Looper实例,并且Looper实例持有的MessageQueue实例也已经创建好了。在当前线程中任何地方调用myLooper()都可以得到唯一的Looper实例。


Looper.prepare()分析完后继续分析internalHandler = new Handler()做了什么工作。
先上Handler的关键源码:

  1. package android.os;
  2. public class Handler {
  3. private static final String TAG = "Handler";
  4. /*当前线程中的消息队列*/
  5. final MessageQueue mQueue;
  6. /*当前队列中的Looper*/
  7. final Looper mLooper;
  8. /*Handler的内部回调,Handler构造器中可以传入Callback,如果传入了此Callback,则Message将交给此Callback的handleMessage去处理,而不是交给Handler的handleMessage去处理*/
  9. final Callback mCallback;
  10. final boolean mAsynchronous;
  11. public interface Callback {
  12. public boolean handleMessage(Message msg);
  13. }
  14. /*Handler有很多构造器,无参构造器的话传入的Callback为null*/
  15. public Handler() {
  16. this(null, false);
  17. }
  18. public Handler(Callback callback) {
  19. this(callback, false);
  20. }
  21. public Handler(boolean async) {
  22. this(null, async);
  23. }
  24. public Handler(Callback callback, boolean async) {
  25. /*获得当前线程中的Looper实例*/
  26. mLooper = Looper.myLooper();
  27. /*如果Looper实例为空,说明当前线程还没有调用Looper.prepare*/
  28. if (mLooper == null) {
  29. throw new RuntimeException(
  30. "Can't create handler inside thread that has not called Looper.prepare()");
  31. }
  32. /*获得当前线程中的消息队列*/
  33. mQueue = mLooper.mQueue;
  34. /*保存构造器传入的callback*/
  35. mCallback = callback;
  36. mAsynchronous = async;
  37. }
  38. /*向消息队列中推送一个Runnable,通过getPostMessage把Runnable封装成Message,调用sendMessageDelayed继续处理*/
  39. public final boolean post(Runnable r) {
  40. return sendMessageDelayed(getPostMessage(r), 0);
  41. }
  42. /*Runnable封装成Message*/
  43. private static Message getPostMessage(Runnable r) {
  44. Message m = Message.obtain();
  45. /*Runnable实例成了Message的callback成员变量*/
  46. m.callback = r;
  47. return m;
  48. }
  49. /*向消息队列中推送一个Message,调用sendMessageDelayed继续处理*/
  50. public final boolean sendMessage(Message msg) {
  51. return sendMessageDelayed(msg, 0);
  52. }
  53. /*sendMessageDelayed调用sendMessageAtTime继续处理*/
  54. public final boolean sendMessageDelayed(Message msg, long delayMillis) {
  55. if (delayMillis < 0) {
  56. delayMillis = 0;
  57. }
  58. return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
  59. }
  60. /*无论是向消息队列中推送Runnable还是Message,最后都走到了这个方法中*/
  61. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
  62. MessageQueue queue = mQueue;
  63. /*如果当前线程的消息队列为null,说明出了问题,推送会失败*/
  64. if (queue == null) {
  65. RuntimeException e = new RuntimeException(
  66. this + " sendMessageAtTime() called with no mQueue");
  67. Log.w("Looper", e.getMessage(), e);
  68. return false;
  69. }
  70. /*把Message推送到消息队列中*/
  71. return enqueueMessage(queue, msg, uptimeMillis);
  72. }
  73. private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
  74. /*把Message的target成员设置成了当前Handler。所以在Looper.loop()中的msg.target.dispatchMessage(msg);即调用了Handler的dispatchMessage*/
  75. msg.target = this;
  76. if (mAsynchronous) {
  77. msg.setAsynchronous(true);
  78. }
  79. /*把Message压入队列*/
  80. return queue.enqueueMessage(msg, uptimeMillis);
  81. }
  82. /*Looper.loop()中获得到待处理的Message后会调度到此处继续处理*/
  83. public void dispatchMessage(Message msg) {
  84. /*msg.callback在getPostMessage方法中赋值,msg.callback即为Runnable,如果Message成员中Runnable不为空则直接处理Runnable*/
  85. if (msg.callback != null) {
  86. handleCallback(msg);
  87. } else {
  88. /*mCallback在Handler构造器中赋值,如果有Callback就交给Callback来处理Message*/
  89. if (mCallback != null) {
  90. if (mCallback.handleMessage(msg)) {
  91. return;
  92. }
  93. }
  94. /*最低优先级是由Handler的handleMessage来处理Message,子类一般会重载Handler的handleMessage*/
  95. handleMessage(msg);
  96. }
  97. }
  98. /*Message成员中Runnable的处理*/
  99. private static void handleCallback(Message message) {
  100. message.callback.run();
  101. }
  102. /*子类重载此方法来处理Message*/
  103. public void handleMessage(Message msg) {
  104. }
  105. }

通过分析Handler的源码,在Handler的构造方法中获得了当前Thread中的Looper实例和Looper实例持有的MessageQueue实例。所以Handler已经和Looper,MessageQueue关联起来了,已经能够通过Handler向MessageQueue中推送消息了。

到目前为止就差处理MessageQueue中的Message了。也就差分析Looper.loop();了,这个loop方法在Looper的源码中已经写了详细的注释了。
所以仅需要在自定义线程中做完3步:
Looper.prepare();
internalHandler = new Handler()
Looper.loop();
就可以通过Handler往当前线程的MessageQueue中推送Message,然后当前线程中的Looper会从MessageQueue中依次取出Message来处理。


Handler在自定义线程中处理Message的情况分析完了,接着分析看看在UI主线程中Handler处理Message的机制是怎么搭建好的呢?
应用程序启动时会创建主线程,即ActivityThread,四大组件无论哪一个启动都是创建的ActivityThread。
上ActivityThread的main方法的源码:

  1. public static void main(String[] args) {
  2. Looper.prepareMainLooper();
  3. ActivityThread thread = new ActivityThread();
  4. if (sMainThreadHandler == null) {
  5. sMainThreadHandler = thread.getHandler();
  6. }
  7. Looper.loop();
  8. throw new RuntimeException("Main thread loop unexpectedly exited");
  9. }

跟自定义Thread中run方法内的差不多,Looper.prepare()换成了Looper.prepareMainLooper(),其实还是同一个Looper实例,只是多了一个Looper.getMainLooper()。new Handler换成了ActivityThread.getHandler()。

上ActivityThread.getHandler()的源码:
  1. final Handler getHandler() {
  2. return mH;
  3. }
  4. final H mH = new H();
  5. private class H extends Handler {}

所以UI主线程中的过程跟自定义线程是一样的。
















声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/143178
推荐阅读
相关标签
  

闽ICP备14008679号