在任意线程给Handler发送的消息为什么会在创建Handler的那个线程被执行?
来源:互联网 发布:网络大电影产值 编辑:程序博客网 时间:2024/06/02 13:41
接触Android一定对Handler不陌生,它是用来处理线程间通信问题。例如如下代码:
public class HandlerTestActivity extends Activity {Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // 在主线程处理这个消息 }};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);new Thread(new Runnable() {@Overridepublic void run() {mHandler.sendEmptyMessage(1);}}).start();}}
那么问题来了,明明是在子线程中发出的消息给Handler,但是为什么最终会在主线程中处理呢?下面来分析下。
分析之前,必须要知道Handler与Looper、MessageQueue和Message的关系,请度娘看看相关资料。
了解以上的关系之后,我们就可以开始探讨上面那个问题:
1、如果我们需要在子线程创建一个Handler时,我们需要这么做:
Looper.prepare();Handler handler = new Handler();Looper.loop();这是首先为当前线程创建一个消息循环Looper给Handler使用,Looper.loop()进行循环获取消息。
延伸:为什么在主线程创建Handler不需要调用Looper.prepare()和Looper.loop()呢?
这是因为系统在启动程序的时候,已经在ActivityThread进行了上面的操作,这是源码:
public static void main(String[] args) { SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
2、我们使用Handler发送消息时,无论在哪个线程发送,最终会把消息保存在消息队列里,也就是保存到MessageQueue里,请看源码:
public class Handler {/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } public final boolean sendMessage(Message msg) { return sendMessageDelayed(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); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } 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);// 将消息保存到MessageQueue queue里面 }}
消息保存到MessageQueue之后,谁来取消息把它给Handler处理呢?没错,就是Looper,请看源码:
public final class Looper {public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; ... for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } ... msg.target.dispatchMessage(msg); // msg.target也就是执行这个消息的Handler ... } }}
所以,整个流程就是这样的:
1、在任意地方通过Handler给自己发送消息Message,并把Message排好队保存在MessageQueue里;
2、Handler所处线程的那个Looper进行循环到MessageQueue里取消息,并把消息按时传到Handler执行。
就这么两步!
所以究竟消息是在哪个线程被Handler处理呢?答案是Looper进行循环的那个线程,也就是创建Handler那个线程。因为是在Looper.loop调用Handler去执行消息的,Looper在哪个线程调用,消息就在哪个线程被Handler处理:
<pre name="code" class="java">msg.target.dispatchMessage(msg); // msg.target也就是执行这个消息的Handler
因为对应Looper所在线程与创建对应Handler的线程必须是同一条,所以无论从哪个线程发送消息给Handler,最终会在创建Handler那个线程执行这个消息。
- 在任意线程给Handler发送的消息为什么会在创建Handler的那个线程被执行?
- Handler详解系列(三)——在子线程中给主线程的消息队列发送消息
- Android学习—— Handler 的消息发送,在新的线程处理消息
- Handler(3)--在子线程中主线程的 消息队列发送消息
- Android Handler 发送消息的线程安全问题
- 在子线程创建handler进行处理消息
- 下面的程序实现了在利用Handler在新线程当中处理消息的方法
- 如何在子线程中创建Handler?
- 创建Handler时,绑定到(指定线程的)消息循环
- 在创建的线程中发送命令响应消息
- Handler的发送消息
- 使用Handler在线程之间传递消息所遇到的问题及解决方法
- 关于handler在子线程中无法给activity传递信息的问题及解决办法
- Looper,handler类实现其他线程接收UI线程发送的消息
- Android异步通信机制简单地理解,Handler是当前线程的消息队列中的一个子队列,而Runable是可以被安排到Handler去运行的接口。 首先在Activity中创建一个继承自Han
- Android的消息机制,用Android线程间通信的Message机制,Android中Handler的使用方法——在子线程中更新界面,handler机制
- Android的消息机制,用Android线程间通信的Message机制,Android中Handler的使用方法——在子线程中更新界面,handler机制
- Android的消息机制,用Android线程间通信的Message机制,Android中Handler的使用方法——在子线程中更新界面,handler机制
- 简单实现类似Spring的在任意代码中获取Request的功能
- Javadoc导出java类的文档结构小结
- Watson之心:DeepQA
- HDU 5372 Segment Game(2015 Multi-University Training Contest 7 1004)
- vivado中改变代码字体的大小
- 在任意线程给Handler发送的消息为什么会在创建Handler的那个线程被执行?
- webservice使用get请求
- 包含对象成员的类 vs普通公有继承的派生类 and 对象成员vs私有继承
- linux学习笔记----目录处理命令----mkdir
- matlab界面语言修改
- hdu 3371 Connect the Cities(prim算法)
- mvc3.0 导出excel文件
- P2P网贷-借款与发标
- [php] Thinkphp自动验证和自动完成