[关闭]
@ZeroGeek 2018-07-03T06:30:21.000000Z 字数 6447 阅读 682

Android的消息机制

基础知识 Android知识点


概述

Looper

消息循环处理器,内部会创建一个MessageQueue,来存放所有消息,主线程是自动创建的,新建的线程需要自己新建一个Looper对象(HandlerThread)。

  1. public final class Looper {
  2. // sThreadLocal.get() will return null unless you've called prepare().
  3. static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
  4. private static Looper sMainLooper; // guarded by Looper.class
  5. final MessageQueue mQueue; // 消息队列,存放消息
  6. final Thread mThread; // 所在线程
  7. // Handler创建前,持有的Looper必须prepare
  8. public static void prepare() {
  9. prepare(true);
  10. }
  11. private static void prepare(boolean quitAllowed) {
  12. if (sThreadLocal.get() != null) {
  13. throw new RuntimeException("Only one Looper may be created per thread");
  14. }
  15. sThreadLocal.set(new Looper(quitAllowed));
  16. }
  17. public static void prepareMainLooper() {
  18. prepare(false);
  19. synchronized (Looper.class) {
  20. if (sMainLooper != null) {
  21. throw new IllegalStateException("The main Looper has already been prepared.");
  22. }
  23. // 返回new的唯一一个ThreadLocal<Looper>,线程独有内存
  24. sMainLooper = myLooper();
  25. }
  26. }
  27. public static Looper getMainLooper() {
  28. synchronized (Looper.class) {
  29. return sMainLooper;
  30. }
  31. }
  32. public static void loop() {
  33. final Looper me = myLooper();
  34. if (me == null) {
  35. throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
  36. }
  37. final MessageQueue queue = me.mQueue;
  38. Binder.clearCallingIdentity();
  39. final long ident = Binder.clearCallingIdentity();
  40. // 无限循环
  41. for (;;) {
  42. Message msg = queue.next(); // might block
  43. if (msg == null) {
  44. return;
  45. }
  46. // ...省略输出Log
  47. msg.target.dispatchMessage(msg);
  48. // ...
  49. msg.recycleUnchecked();
  50. }
  51. }
  52. public static Looper myLooper() {
  53. return sThreadLocal.get();
  54. }
  55. public static MessageQueue myQueue() {
  56. return myLooper().mQueue;
  57. }
  58. private Looper(boolean quitAllowed) {
  59. mQueue = new MessageQueue(quitAllowed);
  60. mThread = Thread.currentThread();
  61. }
  62. public boolean isCurrentThread() {
  63. return Thread.currentThread() == mThread;
  64. }
  65. public void quit() {
  66. mQueue.quit(false);
  67. }
  68. public void quitSafely() {
  69. mQueue.quit(true);
  70. }
  71. // ...
  72. }

prepare() : 多次调用,会产生异常。
loop():无限循环

Handler

负责Message的发送和回调处理

  1. public class Handler {
  2. public interface Callback {
  3. public boolean handleMessage(Message msg);
  4. }
  5. // 必须实现才能处理消息
  6. public void handleMessage(Message msg) {
  7. }
  8. // 由Looper的MessageQueue中的Message持有的Handler对象调用
  9. public void dispatchMessage(Message msg) {
  10. if (msg.callback != null) {
  11. handleCallback(msg);
  12. } else {
  13. if (mCallback != null) {
  14. if (mCallback.handleMessage(msg)) {
  15. return;
  16. }
  17. }
  18. handleMessage(msg);
  19. }
  20. }
  21. public Handler() {
  22. this(null, false);
  23. }
  24. public Handler(Callback callback) {
  25. this(callback, false);
  26. }
  27. public Handler(Looper looper) {
  28. this(looper, null, false);
  29. }
  30. public Handler(Looper looper, Callback callback) {
  31. this(looper, callback, false);
  32. }
  33. public Handler(boolean async) {
  34. this(null, async);
  35. }
  36. public Handler(Callback callback, boolean async) {
  37. mLooper = Looper.myLooper();
  38. // 没准备Looper会抛异常
  39. if (mLooper == null) {
  40. throw new RuntimeException(
  41. "Can't create handler inside thread that has not called Looper.prepare()");
  42. }
  43. mQueue = mLooper.mQueue;
  44. mCallback = callback;
  45. mAsynchronous = async;
  46. }
  47. // 发送消息(就是把Message添加到MessageQueue中)
  48. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
  49. MessageQueue queue = mQueue;
  50. if (queue == null) {
  51. RuntimeException e = new RuntimeException(
  52. this + " sendMessageAtTime() called with no mQueue");
  53. Log.w("Looper", e.getMessage(), e);
  54. return false;
  55. }
  56. return enqueueMessage(queue, msg, uptimeMillis);
  57. }
  58. private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
  59. msg.target = this;
  60. if (mAsynchronous) {
  61. msg.setAsynchronous(true);
  62. }
  63. return queue.enqueueMessage(msg, uptimeMillis);
  64. }
  65. final Looper mLooper;
  66. final MessageQueue mQueue;
  67. final Callback mCallback;
  68. final boolean mAsynchronous;
  69. IMessenger mMessenger;
  70. // ...
  71. }

MessageQueue

消息队列,存放Message,Message是一个链表

  1. public final class MessageQueue {
  2. // True if the message queue can be quit.
  3. private final boolean mQuitAllowed;
  4. @SuppressWarnings("unused")
  5. private long mPtr; // used by native code
  6. Message mMessages;
  7. private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
  8. private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
  9. private IdleHandler[] mPendingIdleHandlers;
  10. private boolean mQuitting;
  11. }

Message

  1. public final class Message implements Parcelable {
  2. // 唯一标识
  3. public int what;
  4. public int arg1;
  5. public int arg2;
  6. public Object obj;
  7. public Messenger replyTo;
  8. public int sendingUid = -1;
  9. /*package*/ static final int FLAG_IN_USE = 1 << 0;
  10. /** If set message is asynchronous */
  11. /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
  12. /** Flags to clear in the copyFrom method */
  13. /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
  14. /*package*/ int flags;
  15. /*package*/ long when;
  16. /*package*/ Bundle data;
  17. // 消息中持有Handler
  18. /*package*/ Handler target;
  19. /*package*/ Runnable callback;
  20. // sometimes we store linked lists of these things
  21. /*package*/ Message next;
  22. private static final Object sPoolSync = new Object();
  23. private static Message sPool;
  24. private static int sPoolSize = 0;
  25. private static final int MAX_POOL_SIZE = 50;
  26. private static boolean gCheckRecycle = true;
  27. }

概述

需要注意的是线程默认是没有Looper的,我们在子线程使用Handler必须先创建Looper否则会发生异常。
至于主线程为什么可以直接使用Handler呢?那是因为主线程在入口的main方法中就已经帮我们创建了一个Looper对象,并开启了一个Looper循环,帮我构建好了这样一个消息消息循环的环境。

总结

在主程序的入口main方法中进行了主线程Looper的创建以及Handler的创建,以及将改Looper与主线程绑定。然后通过Looper.loop方法进行消息的循环,不断的从消息队列(在初始化Looper的构造函数中进行了MessageQueue的初始化)取出消息,然后交给Message所持有的Handler来处理,Handler通过调用dispatchMessage()方法来处理消息。从而形成了整个消息系统机制。注意:因为我们一般使用Handler都是在主线程中,不用考虑Looper的创建,因为刚才说了,启动程序时候默认给我们创建了一个Looper对象,所在在这个环境下我们可以自由使用Handler,但是如果我们要在子线程中使用Handler就必须先通过Looper.prepare()方法创建一个Looper对象,然后创建handler对象然后通过Looper.loop()方法实Loop循环,不断的处理消息。

HandlerThread

在子线程中创建自己的Handler和Looper,独立的消息处理系统。

  1. public class HandlerThread extends Thread {
  2. int mPriority;
  3. int mTid = -1;
  4. Looper mLooper;
  5. private @Nullable Handler mHandler;
  6. public HandlerThread(String name) {
  7. super(name);
  8. mPriority = Process.THREAD_PRIORITY_DEFAULT;
  9. }
  10. public HandlerThread(String name, int priority) {
  11. super(name);
  12. mPriority = priority;
  13. }
  14. protected void onLooperPrepared() {
  15. }
  16. @Override
  17. public void run() {
  18. mTid = Process.myTid();
  19. Looper.prepare();
  20. synchronized (this) {
  21. mLooper = Looper.myLooper();
  22. notifyAll();
  23. }
  24. Process.setThreadPriority(mPriority);
  25. onLooperPrepared();
  26. Looper.loop();
  27. mTid = -1;
  28. }
  29. public Looper getLooper() {
  30. if (!isAlive()) {
  31. return null;
  32. }
  33. // If the thread has been started, wait until the looper has been created.
  34. synchronized (this) {
  35. while (isAlive() && mLooper == null) {
  36. try {
  37. wait();
  38. } catch (InterruptedException e) {
  39. }
  40. }
  41. }
  42. return mLooper;
  43. }
  44. // 可以获取Handler,来分发消息,然后在子线程的消息循环中处理
  45. public Handler getThreadHandler() {
  46. if (mHandler == null) {
  47. mHandler = new Handler(getLooper());
  48. }
  49. return mHandler;
  50. }
  51. public boolean quitSafely() {
  52. Looper looper = getLooper();
  53. if (looper != null) {
  54. looper.quitSafely();
  55. return true;
  56. }
  57. return false;
  58. }
  59. public int getThreadId() {
  60. return mTid;
  61. }
  62. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注