先膜拜下大神的帖子,从源码的角度分析android的Handler机制。 链接:android的消息处理机制(图+源码分析)——Looper,Handler,Message
这里就不赘言,仅仅做一些介绍,想看详细请猛戳上面的链接。
android的消息机制由三块组成Looper,Handler,MessageQueue。我们知道在android中子线程中是不能够执行组件的更新操作的,既然这样我们只能在子线程中把消息发送给主线程,让主线程自己去更新,这里就会用到Handler。子线程通过调用主线程的Handler对象 sendMessage 将消息发送到主线程的Looper所管理的MessageQueue中,消息循环收到消息后就会调用主线程的handler的handleMessage函数处理消息,这样就实现了线程间通信。
在Activity中,存在默认的消息队列和消息循环,当创建Handler的时候(重写handleMessage方法),handler自身包含三个对象
final MessageQueue mQueue; // 关联的MQ
final Looper mLooper; // 关联的looper
final Callback mCallback;
将自身的三个对象关联当前线程Looper和MessageQueue。在子线程中调用sendMessage就会 将消息发送给handler所在线程的MessageQueue中,最后消息循环会调用handler的handleMessage()
在android中,每隔线程都可以拥有自己写的消息队列和消息循环。默认创建的子线程是没有消息队列和消息循环的,如果想要子线程拥有消息队列和消息循环,就需要在线程中调用Looper.prepare()来创建消息队列,然后调用Looper.loop()来进入消息循环。
例如:
public class LooperThread extends Thread { @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare(); // ...其他处理,如实例化handler // 开始循环处理消息队列 Looper.loop(); } }
在Looper.prepare里面会创建一个Looper对象,并放在ThreadLocal里面,可以通过Looper.myLooper获得当前线程的Looper对象,通过Looper.getMainLooper 获得当前线程的主线程的Looper对象。
public static final Looper myLooper() { // 在任意线程调用Looper.myLooper()返回的都是那个线程的looper return (Looper)sThreadLocal.get(); }
调用Looper.loop()会开启消息循环。
最后需要注意几点:
1.尽管Message有public的默认构造方法,但是你应该通过Message.obtain()来从消息池中获得空消息对象,以节省资源。
2.如果你的message只需要携带简单的int信息,请优先使用Message.arg1和Message.arg2来传递信息,这比用Bundle更省内存
3.擅用message.what来标识信息,以便用不同方式处理message。