[关闭]
@yudesong 2018-02-12T03:12:13.000000Z 字数 2542 阅读 622

Handler机制

Handler


正如郭大神所说的那样:

Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃。相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟于心,即创建一个Message对象,然后借助Handler发送出去,之后在Handler的handleMessage()方法中获得刚才发送的Message对象,然后在这里进行UI操作就不会再出现崩溃了。

首先,来看看Handle的源码

  1. public Handler() {
  2. if (FIND_POTENTIAL_LEAKS) {
  3. final Class<? extends Handler> klass = getClass();
  4. if ((klass.isAnonymousClass() || klass.isMemberClass()
  5. || klass.isLocalClass()) &&
  6. (klass.getModifiers() & Modifier.STATIC) == 0) {
  7. Log.w(TAG, "The following Handler class should be
  8. static or leaks might occur: " +
  9. klass.getCanonicalName());
  10. }
  11. }
  12. mLooper = Looper.myLooper();
  13. if (mLooper == null) {
  14. throw new RuntimeException(
  15. "Can't create handler inside thread that
  16. has not called Looper.prepare()");
  17. }
  18. mQueue = mLooper.mQueue;
  19. mCallback = null;
  20. }
  21. public static final void prepare() {
  22. if (sThreadLocal.get() != null) {
  23. throw new RuntimeException("Only one Looper may be created per thread");
  24. }
  25. sThreadLocal.set(new Looper());
  26. }
  27. public static final Looper myLooper() {
  28. return (Looper)sThreadLocal.get();
  29. }

接下来看看Handler是如何传递消息的

  1. public boolean sendMessageAtTime(Message msg, long uptimeMillis)
  2. {
  3. boolean sent = false;
  4. MessageQueue queue = mQueue;
  5. if (queue != null) {
  6. msg.target = this;
  7. sent = queue.enqueueMessage(msg, uptimeMillis);
  8. }
  9. else {
  10. RuntimeException e = new RuntimeException(
  11. this + " sendMessageAtTime() called with no mQueue");
  12. Log.w("Looper", e.getMessage(), e);
  13. }
  14. return sent;
  15. }
  16. final boolean enqueueMessage(Message msg, long when) {
  17. if (msg.when != 0) {
  18. throw new AndroidRuntimeException(msg
  19. + " This message is already in use.");
  20. }
  21. if (msg.target == null && !mQuitAllowed) {
  22. throw new RuntimeException("Main thread not allowed to quit");
  23. }
  24. synchronized (this) {
  25. if (mQuiting) {
  26. RuntimeException e = new RuntimeException(msg.target
  27. + " sending message to a Handler on a dead thread");
  28. Log.w("MessageQueue", e.getMessage(), e);
  29. return false;
  30. } else if (msg.target == null) {
  31. mQuiting = true;
  32. }
  33. msg.when = when;
  34. Message p = mMessages;
  35. if (p == null || when == 0 || when < p.when) {
  36. msg.next = p;
  37. mMessages = msg;
  38. this.notify();
  39. } else {
  40. Message prev = null;
  41. while (p != null && p.when <= when) {
  42. prev = p;
  43. p = p.next;
  44. }
  45. msg.next = prev.next;
  46. prev.next = msg;
  47. this.notify();
  48. }
  49. }
  50. return true;
  51. }
  52. public static final void loop() {
  53. Looper me = myLooper();
  54. MessageQueue queue = me.mQueue;
  55. while (true) {
  56. Message msg = queue.next(); // might block
  57. if (msg != null) {
  58. if (msg.target == null) {
  59. return;
  60. }
  61. if (me.mLogging!= null) me.mLogging.println(
  62. ">>>>> Dispatching to " + msg.target + " "
  63. + msg.callback + ": " + msg.what
  64. );
  65. msg.target.dispatchMessage(msg);
  66. if (me.mLogging!= null) me.mLogging.println(
  67. "<<<<< Finished to " + msg.target + " "
  68. + msg.callback);
  69. msg.recycle();
  70. }
  71. }
  72. }
  73. public void dispatchMessage(Message msg) {
  74. if (msg.callback != null) {
  75. handleCallback(msg);
  76. } else {
  77. if (mCallback != null) {
  78. if (mCallback.handleMessage(msg)) {
  79. return;
  80. }
  81. }
  82. handleMessage(msg);
  83. }
  84. }

参考文献
1.Android异步消息处理机制完全解析,带你从源码的角度彻底理解

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注