by hzwusibo 20190504
handler的原理, loop怎么与handler进行绑定https://blog.csdn.net/lqb3732842/article/details/54947159handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有handler进行Message的分发与处理。
https://blog.csdn.net/lmj623565791/article/details/38377229Handler的创建流程
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法, 为啥Handler可以成功创建呢?
因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。
loop自循环为什么不会阻塞
https://blog.csdn.net/u013435893/article/details/50903082
Android是事件驱动,Looper内部是一个while死循华,只有程序退出后循环才会停止,如果Looper使用中死掉了,任何事件都不会有反应了。事件只会阻塞Looper,而Looper不会阻塞事件。
ActivityThread 有个 getHandler 方法,得到这个 handler 就可以发送消息,然后 loop 里就分发消息,然后就发给 handler, 然后就执行到 H(Handler )里的对应代码。所以这些代码就不会卡死~,有消息过来就能执行。举个例子,在 ActivityThread 里的内部类 ApplicationThread 中就有很多 sendMessage 的方法。
简单的来说:
ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的程序也就可以退出了。
从消息队列中取消息可能会阻塞,取到消息会做出相应的处理。如果某个消息处理时间过长,就可能会影响UI线程的刷新速率,造成卡顿的现象。
主要原因有2个
1、epoll模型 当没有消息的时候会epoll.wait,等待句柄写的时候再唤醒, 主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。
2、所有的ui操作都通过handler来发消息操作。 比如屏幕刷新16ms一个消息,你的各种点击事件,所以就会有句柄写操作,唤醒上文的wait操作,所以不会被卡死了。
主线程的死循环一直运行是不是特别消耗CPU资源呢? 这里涉及到Linux pipe/epoll机制,简单说就是在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce()方法,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。 所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。
https://www.zhihu.com/question/34652589
子线程和子线程之间的通信