源码分析 Handler 机制(一) —— Handler

本文基于 SDK-33

Handler 如何创建:

  1. 无参构造方法(已弃用)

    @Deprecated
    public Handler() {
        this(null, false);
    }
    
  2. Callback 作为参数(已弃用)

    public Handler(@Nullable Callback callback) {
        this(callback, false);
    }
    
  3. Looper 作为参数

      public Handler(@NonNull Looper looper) {
          this(looper, null, false);
      }
    
  4. Looper、Callback 作为参数

      public Handler(@NonNull Looper looper, @Nullable Callback callback) {
          this(looper, callback, false);
      }
    
  5. 异步消息标志作为参数(不对外公开)

      public Handler(boolean async) {
          this(null, async);
      }
    
  6. Callback 、异步消息标志作为参数(不对外公开)

      public Handler(@Nullable Callback callback, boolean async) {
          if (FIND_POTENTIAL_LEAKS) {
              final Class<? extends Handler> klass = getClass();
              if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                      (klass.getModifiers() & Modifier.STATIC) == 0) {
                  Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                      klass.getCanonicalName());
              }
          }
    
          mLooper = Looper.myLooper();
          if (mLooper == null) {
              throw new RuntimeException(
                  "Can't create handler inside thread " + Thread.currentThread()
                          + " that has not called Looper.prepare()");
          }
          mQueue = mLooper.mQueue;
          mCallback = callback;
          mAsynchronous = async;
      }
    
  7. Looper、Callback、异步消息标志作为参数(不对外公开)

      public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
          mLooper = looper;
          mQueue = looper.mQueue;
          mCallback = callback;
          mAsynchronous = async;
      }
    
  8. 创建不进行自定义消息处理的异步处理 Handler

      public static Handler createAsync(@NonNull Looper looper) {
          if (looper == null) throw new NullPointerException("looper must not be null");
          return new Handler(looper, null, true);
      }
    
  9. 创建可以处理自定义消息的异步处理 Handler

      public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
          if (looper == null) throw new NullPointerException("looper must not be null");
          if (callback == null) throw new NullPointerException("callback must not be null");
          return new Handler(looper, callback, true);
      }
    

方法好几个,但其实可以这样划分:

  1. 创建受同步障碍约束的 Handler(3、4)
  2. 创建不受同步障碍约束的 Handler(8、9)

关于同步障碍,MessageQueue 中会讲到

但是不管是哪种方式创建,都会走到 6 或 7,但不管是哪一种创建方式,都执行了这些初始化操作:

  1. 为 Handler 指定了 Looper
  2. 指定了 MessageQueue
  3. 指定了 Callback(如果有的话,没有则为 null)
  4. 指定了发送的消息是同步还是异步

Handler 如何发送消息

sendXXX

  • 发送普通消息:

      public final boolean sendMessage(@NonNull Message msg) {
          return sendMessageDelayed(msg, 0);
      }
    
  • 发送普通延时消息

      public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
          if (delayMillis < 0) {
              delayMillis = 0;
          }
          return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
      }
    
  • 发送特定时间执行的普通消息

      public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
          MessageQueue queue = mQueue;
          if (queue == null) {
              RuntimeException e = new RuntimeException(
                      this + " sendMessageAtTime() called with no mQueue");
              Log.w("Looper", e.getMessage(), e);
              return false;
          }
          return enqueueMessage(queue, msg, uptimeMillis);
      }
    
  • 发送插队的普通消息

      public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
          MessageQueue queue = mQueue;
          if (queue == null) {
              RuntimeException e = new RuntimeException(
                  this + " sendMessageAtTime() called with no mQueue");
              Log.w("Looper", e.getMessage(), e);
              return false;
          }
          return enqueueMessage(queue, msg, 0);
      }
    
  • 发送空消息:

      public final boolean sendEmptyMessage(int what){
          return sendEmptyMessageDelayed(what, 0);
      }
    
  • 发送延时空消息

      public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
          Message msg = Message.obtain();
          msg.what = what;
          return sendMessageDelayed(msg, delayMillis);
      }
    
  • 发送特定时间执行的空消息

      public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
          Message msg = Message.obtain();
          msg.what = what;
          return sendMessageAtTime(msg, uptimeMillis);
      }
    

这些方法最终都会调用到 enqueueMessage 方法:

    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

可以看到该方法执行了这些操作:

  1. 将 Message 的 target 设置为此 Handler
  2. 将 Message 的同步标志设置(在 Handler 创建时,指定了 mAsynchronous 的值)
  3. 调用 MessageQueue 的 enqueueMessage 方法将消息传入队列中

MessageQueue 后面会写。

postXXX

  • 发送一个 Runnable 对象

      public final boolean post(@NonNull Runnable r) {
         return  sendMessageDelayed(getPostMessage(r), 0);
      }
    
  • 发送一个定时的 Runnable 对象(不带 Token)

      public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
          return sendMessageAtTime(getPostMessage(r), uptimeMillis);
      }
    
  • 发送一个定时的 Runnable 对象(带 Token)

      public final boolean postAtTime(
              @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
          return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
      }
    
  • 发送一个延时执行的 Runnable 对象

      public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
          return sendMessageDelayed(getPostMessage(r), delayMillis);
      }
    
  • 发送一个延时带 what 标记的 Runnable 对象(不对外公开)

      public final boolean postDelayed(Runnable r, int what, long delayMillis) {
          return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);
      }
    
  • 发送一个延时带 Token 的 Runnable 对象

      public final boolean postDelayed(
              @NonNull Runnable r, @Nullable Object token, long delayMillis) {
          return sendMessageDelayed(getPostMessage(r, token), delayMillis);
      }
    
  • 发送一个插队的 Runnable 对象

      public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
          return sendMessageAtFrontOfQueue(getPostMessage(r));
      }
    

postXXX 方法要点在于对 getPostMessage 方法的调用:

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

    @UnsupportedAppUsage
    private static Message getPostMessage(Runnable r, Object token) {
        Message m = Message.obtain();
        m.obj = token;
        m.callback = r;
        return m;
    }

所以 postXXX 本质上还是通过 sendXXX 来发送消息的,只不过是为将 Message 的 callback 设置为我们的 Runnable 对象,通过 sendXXX 发送的消息不会设置 Callback

移除消息

调用 Handler 对象的移除消息方法,最终调用的是 MessageQueue 中对应的 removeMessage 方法:

    public final void removeCallbacks(@NonNull Runnable r) {
        mQueue.removeMessages(this, r, null);
    }

    public final void removeCallbacks(@NonNull Runnable r, @Nullable Object token) {
        mQueue.removeMessages(this, r, token);
    }

    public final void removeMessages(int what) {
        mQueue.removeMessages(this, what, null);
    }

    public final void removeMessages(int what, @Nullable Object object) {
        mQueue.removeMessages(this, what, object);
    }

    public final void removeCallbacksAndMessages(@Nullable Object token) {
        mQueue.removeCallbacksAndMessages(this, token);
    }

具体移除过程,会在 MessageQueue 文章中讲解。

分发消息 dispatchMessage

这个方法看注释就好了:

    public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);//如果 Message 设置了 Runnable,则直接执行
        } else {
            if (mCallback != null) {//如果 Handler 设置了 Callback,则消息优先交给 Callback 处理
                if (mCallback.handleMessage(msg)) {//如果 Callback 处理了 Message,则直接返回,不再经过 handleMessage 方法
                    return;
                }
            }
            handleMessage(msg);//handleMessage 方法处理 Message
        }
    }

上面就是最常用的 Handler 功能,Handler 还有一些其他功能:

通过 Handler 创建 Message

    public final Message obtainMessage(){
        return Message.obtain(this);
    }

    public final Message obtainMessage(int what){
        return Message.obtain(this, what);
    }

    public final Message obtainMessage(int what, @Nullable Object obj) {
        return Message.obtain(this, what, obj);
    }

    public final Message obtainMessage(int what, @Nullable Object obj) {
        return Message.obtain(this, what, obj);
    }

    public final Message obtainMessage(int what, int arg1, int arg2){
        return Message.obtain(this, what, arg1, arg2);
    }

    public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
        return Message.obtain(this, what, arg1, arg2, obj);
    }

可以看到,Handler 创建 Message 实际上还是调用了 Message 创建对象的方法,只不过是把自身作为参数传入了 Message 的 obtain 方法,为 Message 设置了 target,关于 Message 后面会有专门文章分析。

检查队列中的 Callback 和 Message

    //检查队列中是否有未处理的对应 what 的 Message
    public final boolean hasMessages(int what) {
        return mQueue.hasMessages(this, what, null);
    }

    //检查队列中是否有未处理的、对应 what、obj == object 的 Message
    public final boolean hasMessages(int what, @Nullable Object object) {
        return mQueue.hasMessages(this, what, object);
    }

    //检查消息队列中是否有未处理的、带有 Callback 的 Message
    public final boolean hasCallbacks(@NonNull Runnable r) {
        return mQueue.hasMessages(this, r, null);
    }

获取 Looper

获取和当前 Handler 绑定的 Looper:

    public final Looper getLooper() {
        return mLooper;
    }
Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1