在任意线程给Handler发送的消息为什么会在创建Handler的那个线程被执行?

    接触Android一定对Handler不陌生,它是用来处理线程间通信问题。例如如下代码:

public class HandlerTestActivity extends Activity {

	Handler mHandler = new Handler() {
	    @Override
	    public void handleMessage(Message msg) {
	    	// 在主线程处理这个消息
	    }
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		new Thread(new Runnable() {
			
			@Override
			public 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那个线程执行这个消息。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值