handler机制

handler机制

 一个handler在被new出来的时候,会从当前所在的线程当中取出一个Looper,之后通过这个handler发送的消息,会被加入到这个looper所持有的messageQueue,Looper会在执行.loop()方法之后开启一个死循环,不断从这个messageQueue中取出message来执行。
 而我们Android的ui线程,也就是activityThread在main方法中就会开启一个Looper。调用Looper的prepareMainLooper()方法,该方法会继续调用prepare()方法,而prepare方法则会new出来一个新的looper对象,存入当前线程当中。之后,会new一个handler作为mainThreadHandler来处理所有的ui线程中的事件。
 而在looper的死循环中,有一个重要的调用:msg.target.dispatchMessage(msg);其中msg指的就是使用handler发送的消息,而msg.target则是发送这条消息的handler本身,在调用handler.sendMessage(message)的时候都会将最终要发送的message消息的target指向自己。

public void dispatchMessage(Message msg) {
    //如果callback不为空,说明发送消息的时候是post一个Runnable对象
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {//这个是用来拦截消息的
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);//最终调用我们重写的handleMessage方法
    }
}

最后在dispatchMessage中,msg.callback其实是在handler.post(runnable)的时候被赋值的,通过一个getPostMessage(runnable)方法将runnable对象赋予msg.callback。所以平时我们执行View.post 这样的方法,就是通过这种方式将runnable交给了ui线程当中的handler去执行,从而实现异步调度。
  自己在子线程中创建Looper的这种需求,比如说想在子线程中弹toast,那么可以先Looper.prepare 然后弹一个吐司,最后调用Looper.loop就可以弹出来了。本质原因是toast操作的是window。所以吐司其实是跟activity平级的存在,不受限于子线程中不可以更新ui的限制。一般需要在ui线程中调用吐司,只是因为吐司需要通过Looper中的messageQueue队列来实现排队显而已,而子线程默认是没有looper的。

参考文章:Handle的原理(Looper、Handler、Message三者关系)

你可能感兴趣的:(Android)