1、Looper总体流程

1-1、Looper.prepare()

  • sThreadLocal是一个ThreadLocal对象,可以用来储存Looper
  • 先调用sThreadLocal.get()取出Looper对象,判断是否为null,不为空则抛出异常,说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper实例
  • 如果sThreadLocal.get()为null,则实例化一个Looper的实例放入了ThreadLocal

    1. /**
    2. * 将当前线程初始化成Looper,使用前要调用loop,退出后要调用quit
    3. */
    4. public static void prepare() {
    5. prepare(true);
    6. }
    7. private static void prepare(boolean quitAllowed) {
    8. // 保证了一个线程中只有一个Looper实例
    9. if (sThreadLocal.get() != null) {
    10. throw new RuntimeException("Only one Looper may be created per thread");
    11. }
    12. sThreadLocal.set(new android.os.Looper(quitAllowed));
    13. }

    1-2、Looper构造方法

    1. /**
    2. * Looper构造方法
    3. * @param quitAllowed
    4. */
    5. private Looper(boolean quitAllowed) {
    6. // 实例化一个消息队列
    7. mQueue = new MessageQueue(quitAllowed);
    8. // 保存当前线程
    9. mThread = Thread.currentThread();
    10. }

    1-3、Looper.loop()

  • 调用完Looper.prepare()方法,我们才能调用Looper.loop方法。(loop方法中我们先调用了myLooper()取出当前的Looper对象,如果为null,系统会抛出异常,提示我们没有调用Looper.prepare()方法 )

  • myLooper()方法取出之前的Looper对象,再取出里面的MessageQueue,通过一个for死循环轮询里面的消息
  • MessageQueue.next取出一个消息,如果消息为null,return并阻塞,如果有消息就调用msg.target.dispatchMessage(msg)进行消息分发,这个target就是Handler,最终在Handler的handlerMessage处理消息

    1. /**
    2. * loop循环消息队列
    3. */
    4. public static void loop() {
    5. // 1 取出当前的Looper,为空则证明没有执行prepare方法,抛出异常
    6. final android.os.Looper me = myLooper();
    7. if (me == null) {
    8. throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    9. }
    10. // 2 拿到该looper实例中的mQueue(消息队列)
    11. final MessageQueue queue = me.mQueue;
    12. // 3 循环消息队列中消息
    13. for (;;) {
    14. // 4 取出一条消息,如果没有消息则阻塞
    15. Message msg = queue.next(); // might block
    16. if (msg == null) {
    17. // No message indicates that the message queue is quitting.
    18. return;
    19. }
    20. // 5 使用调用 msg.target.dispatchMessage(msg);
    21. // 把消息交给msg的target的dispatchMessage方法去处理(msg.target就是Handler)
    22. try {
    23. msg.target.dispatchMessage(msg);
    24. } finally {
    25. if (traceTag != 0) {
    26. Trace.traceEnd(traceTag);
    27. }
    28. }
    29. }
    30. }

    1-4、loop空消息会阻塞

  • 点击loop,日志如下

    • D/MainActivity: prepare before
    • D/MainActivity: prepare after
  • 点击quit,日志如下

    • D/MainActivity: loop after

      1. private Looper looper;
      2. public void loop(View view) {
      3. new Thread(new Runnable() {
      4. @Override
      5. public void run() {
      6. Log.d(TAG, "prepare before");
      7. Looper.prepare();
      8. looper = Looper.myLooper();
      9. Log.d(TAG, "prepare after");
      10. // MessageQueen中消息空则会阻塞线程
      11. Looper.loop();
      12. Log.d(TAG, "loop after");
      13. }
      14. }).start();
      15. }
      16. public void quit(View view) {
      17. looper.quit();
      18. }

      1-5、Looper常见方法

  • prepare:初始化当前线程的Looper

  • loop:循环消息队列
  • quit:退出消息队列
  • myLooper:获取当前线程的Looper对象
  • getMainLooper:获取主线程的Looper对象
  • prepareMainLooper:初始化主线程的Looper

    2、Looper简化的代码

    ``` public final class Looper {

    /**

    • ThreadLocal并不是线程,它的作用是存储Looper */ // sThreadLocal.get() will return null unless you’ve called prepare() static final ThreadLocal sThreadLocal = new ThreadLocal();

      /**

    • 主线程的Looper */ private static android.os.Looper sMainLooper;

      /**

    • 消息队列 */ final MessageQueue mQueue;

      /**

    • 当前线程Thread */ final Thread mThread;

      /**

    • 将当前线程初始化成Looper,使用前要调用loop,退出后要调用quit */ public static void prepare() { prepare(true); }

      private static void prepare(boolean quitAllowed) { // 保证了一个线程中只有一个Looper实例 if (sThreadLocal.get() != null) {

      1. throw new RuntimeException("Only one Looper may be created per thread");

      } sThreadLocal.set(new android.os.Looper(quitAllowed)); }

      /**

    • Looper构造方法
    • @param quitAllowed */ private Looper(boolean quitAllowed) { // 实例化一个消息队列 mQueue = new MessageQueue(quitAllowed); // 保存当前线程 mThread = Thread.currentThread(); }

      /**

    • 获取与当前线程关联的Looper,如果没有先调用prepare这里会返回空 */ public static @Nullable android.os.Looper myLooper() { return sThreadLocal.get(); }

      /**

    • loop循环消息队列 */ public static void loop() {

      // 1 取出当前的Looper,为空则证明没有执行prepare方法,抛出异常 final android.os.Looper me = myLooper(); if (me == null) {

      1. throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

      }

      // 2 拿到该looper实例中的mQueue(消息队列) final MessageQueue queue = me.mQueue;

      // 3 循环消息队列中消息 for (;;) {

      1. // 4 取出一条消息,如果没有消息则阻塞
      2. Message msg = queue.next(); // might block
      3. if (msg == null) {
      4. // No message indicates that the message queue is quitting.
      5. return;
      6. }
      7. // 5 使用调用 msg.target.dispatchMessage(msg);
      8. // 把消息交给msg的target的dispatchMessage方法去处理(msg.target就是Handler)
      9. try {
      10. msg.target.dispatchMessage(msg);
      11. } finally {
      12. if (traceTag != 0) {
      13. Trace.traceEnd(traceTag);
      14. }
      15. }

      } }

  1. /**
  2. * 退出Looper
  3. */
  4. public void quit() {
  5. mQueue.quit(false);
  6. }
  7. /**
  8. * Android 环境会创建主线程 Looper,开发者不应该自己调用这个方法。
  9. * UI线程,它就是 ActivityThread
  10. * ActivityThread 被创建时就会初始化 Looper,这也是在主线程中默认可以使用 Handler 的原因
  11. */
  12. @Deprecated
  13. public static void prepareMainLooper() {
  14. prepare(false);
  15. synchronized (android.os.Looper.class) {
  16. if (sMainLooper != null) {
  17. throw new IllegalStateException("The main Looper has already been prepared.");
  18. }
  19. sMainLooper = myLooper();
  20. }
  21. }
  22. /**
  23. * 获取主线程的Looper
  24. * @return
  25. */
  26. public static android.os.Looper getMainLooper() {
  27. synchronized (android.os.Looper.class) {
  28. return sMainLooper;
  29. }
  30. }

} ```