首先从Handler 的构造方法开始,Handler有几种构造方法,先从最开始的最普通的开始,Handelr handler = new handler();
点进去 看源码:
publicHandler() {
this(null,false);
}
进去后回发现其中调用了
mLooper= Looper.myLooper();
mQueue=mLooper.mQueue;
即会添加该线程上对应的一个Looper对象,然后拿到该线程对应的MessageQueue,将创建的handler与该Looper绑定成对应关系,其中Looper是通过ThreadLocal(java的一个类,可以通过它得到一个线程与相应变量的Map,即通过它实现了Looper线程的唯一性)实现与每个线程做绑定一一对应的,即每个线程可通过ThreadLocal拿到其对应的那个Looper(前提是有),即一个线程最多对应一个Looper,而每个Looper又管理一个消息队列(MessageQueue),而Handler即负责把消息传给队列的,消息为Message,是谷歌封装的一个消息类,里面可以传普通的东西,也有callBack,你想让handlerMesage的执行在哪个线程,就要把消息扔到对应线程的MessageQueue里,而最开始构造方法里就是会有对handler里设置其对应的MessageQueue,即创建它的线程上执行。其中也有其他的构造方法,可以把其他线程对应的Looper设进去,实现在另一线程上运行。那么为什么塞到对应的MessageQueue里就可以在对应线程上执行了呢?因为Looper所谓对应一个线程,是指Looper在创建时会立刻执行loop方法,即loop方法是在其对应的那个线程上执行的,loop方法逻辑理解上比较单纯,即是一个死循环不停地从MessageQueue里拿数据,一旦有Message来了,就会在该线程执行里面的之前post进来的Runnable,或者对Message执行对应HandleMessage,即handler只是在子线程把消息放进消息队列里,然后系统时间片轮转时切换线程,继续死循环遍历MessageQueue,一旦来了就执行,即最后执行是在loop的线程上,即Looper创建的那个,即其对应的那个线程。
Handler把消息扔进消息队列,message会存有该Handler的引用,这样在从消息队列抽出来时,消息会被其对应的Handler执行。
最后一个,即为什么loop这个死循环会在主线程执行,不会ANR么?答,最开始Android的入口ActivityThread里面的main方法,里面有一个巨大的Handler,然后会创建一个主线程的looper对象,这也是为什么直接在主线程拿Handler就有Looper的原因,在其他线程是要自己Looper.prepare()的。其实整个Android就是在一个Looper的loop循环的,整个Androidi的一切都是以Handler机制进行的,即只要有代码执行都是通过Handler来执行的,而所谓ANR便是🈯️Looper.loop没有得到及时处理,一旦没有消息,Linux的epoll机制则会通过管道写文件描述符的方式来对主线程进行唤醒与沉睡,android里调用了linux层的代码实现在适当时会睡眠主线程。
网友评论