返回介绍

SendMessage

发布于 2024-12-23 21:36:39 字数 5111 浏览 0 评论 0 收藏 0

我们使用 Handler 发送消息

mHandler.sendMessage(msg);

Handler 有好多相关的发送消息的方法。但是追踪源码,发现他们最终都来到了 Handler 的这个方法 sendMessageAtTime

public boolean sendMessageAtTime(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);
}

接着看 enqueueMessage() 方法体

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    // 使用默认的 handler 构造方法时,mAsynchronous 为 false。
    if (mAsynchronous) {
      msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
  }

这里有一句至关重要的代码

msg.target = this;

我们看看 msg 的 target 是怎么声明的

Handler target;

意思就是每个 Message 都有一个类型为 Handler 的 target 对象,这里在 handler 发送消息的时候,最终执行到 上面的方法 enqueueMessage() 时,会自动把当前执行 sendMessage() 的 handler 对象,赋值给 Message 的 target。

也就是说,Handler 发送了 Message,并且这个 Message 的 target 就是这个 Handler。

想想为什么要这么做?

这里再说一下,Handler 的作用,

  • 发送消息
  • 处理消息

先不看代码,我们可以想想,handler 发送了 message ,最终这个 message 会被发送到 MessageQueue 这个消息队列。 那么最终,谁会去处理这个消息。

在这里消息发送和处理遵循『谁发送,谁处理』的原则。现在问题来了,就按照上面说的,谁发送,谁处理,那现在应该是 handler 自己处理了,但是他在哪里处理呢?到现在我们也没看到啊。慢慢来,接下来继续看消息的传递。

现在,我们只要发送了消息,那么消息池 mQueue 就会增加一个消息,Looper 就会开始工作,之前已经说了,在应用启动的时候, 已经启动了 Looper 的 loop() 方法,这个方法会不断的去轮训 mQueue 消息池,只要有消息,它就会取出消息,并处理,那他是怎么处理的呢?看一下 loop() 的代码再说。

public static void loop() {

  //获得一个 Looper 对象
  final Looper me = myLooper();

  // 拿到 looper 对应的 mQueue 对象
  final MessageQueue queue = me.mQueue;

  //死循环监听(如果没有消息变化,他不会工作的) 不断轮训 queue 中的 Message
  for (;;) {
    // 通过 queue 的 next 方法拿到一个 Message
    Message msg = queue.next(); // might block
    //空判断
    if (msg == null)return;
    //消息分发   
    msg.target.dispatchMessage(msg);
    //回收操作  
    msg.recycleUnchecked();
  }
}

看 for() 循环,他在拿到消息后,发现 msg 不为空,接着就会执行下面这句非常重要的代码

msg.target.dispatchMessage(msg);

这里执行了 msg.target 的方法 dispatchMessage,上面已经在 sendMessage 时看到了,我们在发送消息时,会把 msg 的 target 设置为 handler 本身,也就是说,handler 发送了消息,最终自己处理了自己刚刚分发的消息。恩恩,答案就在这里,『谁发送,谁处理』的 道理在这里终于得到了体现。

那么他是怎么处理消息的?看看 Handler 的 dispatchMessage() 是怎么实现的。

public void dispatchMessage(Message msg) {
  if (msg.callback != null) {
    handleCallback(msg);
  } else {
    if (mCallback != null) {
      if (mCallback.handleMessage(msg)) {
        return;
      }
    }
    handleMessage(msg);
  }
}

我们看到,我们没有给 msg 设置 callback 也没有给 handler 的 mCallback 设置过值,所以此时,会执行 handleMessage() 方法;

public void handleMessage(Message msg) {

}

发现这是一个空方法,所以自己的新建 Handler 时,只要复写了这个方法,我们就可以接受到从子线程中发送过来的消息了 。在看一遍自己定义 Handler 时,如何定义的,如何复写 handlerMessage

private Handler mHandler = new Handler(){
   @Override
   public void handleMessage(Message msg) {
     super.handleMessage(msg);
     switch (msg.what){
       case 1:
         Bitmap bitmap = (Bitmap) msg.obj;
         imageView.setImageBitmap(bitmap);
         break;
       case -1:
         Toast.makeText(MainActivity.this, "msg "+msg.obj.toString(), Toast.LENGTH_SHORT).show();
         break;
     }
   }
 };

在这里,我们处理了自己发送的消息,到此 Handler 的内部机制大体就分析完了。但是从上面的 dispatchMessage 方法我们也能看出,Handler 在处理消息时的顺序是什么?

public void dispatchMessage(Message msg) {
  if (msg.callback != null) {
    handleCallback(msg);
  } else {
    if (mCallback != null) {
      if (mCallback.handleMessage(msg)) {
        return;
      }
    }
    handleMessage(msg);
  }
}

他首先判断 Message 对象的 callback 对象是不是为空,如果不为空,就直接调用 handleCallback 方法,并把 msg 对象传递过去,这样消息就被处理了,我们来看 Message 的 handleCallback 方法:

private static void handleCallback(Message message) {
  message.callback.run();
}

没什么好说的了,直接调用 Handler post 的 Runnable 对象的 run() 方法。

如果在发送消息时,我们没有给 Message 设置 callback 对象,那么程序会执行到 else 语句块,此时首先判断 Handler 的 mCallBack 对象是不是空的,如果不为空,直接调用 mCallback 的 handleMessage 方法进行消息处理。

最终,只有当 Handler 的 mCallback 对象为空,才会执行自己的 handleMessage 方法。

这是整个处理消息的流程。现在就会想了,在处理消息时,什么时候才能执行到第一种情况呢,也就是通过 Message 的 callback 对象处理。其实简单,查看源码发现

/*package*/ Runnable callback;

callback 是一个 Runnable 接口,那我们这怎么才能设置 Message 的 callback 的参数呢?最后观察发现,Handler 发送消息时,除了使用 sendMessage 方法,还可以使用一个叫 post 的方法,而他的形参正好就是 Runnable,我们赶紧拔出他的源码看看。

public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}

接着看 getPostMessage() 这个方法。

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

代码看到这里,已经很清楚了,getPostMessage() 返回了一个 Message 对象,这个对象中设置了刚才传递过来的 runnable 对象。

到这里,你应该明白了,在处理消息时,除了 Handler 自身的 handlerMessage() 方法设置处理,还可以直接在发消息时指定一个 runnable 对象用于处理消息。

另外上面通过 dispatchMessage() 的代码已经看出来,处理消息有三种情形,第一种直接使用 Message 的 running 对象处理,如果不行使用第二种 用 Handler 的 mCallback 对象处理,最后才考虑使用 handlerMessage 处理,关于第二种情形,这里就不分析了,自己试着看代码应该能找到。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文