Handler代表了Android系统中的消息机制,Android系统中所有的事件都是通过Handler进行传递的。
要理解Handler就不得不知道这几个类 Looper、MessageQueue、ThreadLocal、Thread、ActivityThrad、Message
类介绍
MessageQueue
单链数据结构,用来储存管理系统中的消息
Message
重点是Message的when属性,他代表了消息执行的时间,MessageQueue通过判断当前时间是否大于Message的when时间来判断是否将Message发送非Looper执行
我们通过mHandler.sendMessageDelayed(Message , 1000);发送一个Message的时候实际上就设置这个消息的执行时间是当前时间的1000毫秒之后等同于mHandler.sendMessageAtTime(Message, SystemClock.uptimeMillis() + 1000);
ThreadLocal
ThreadLocal解决了多线程程序的并发问题
它为每一个线程提供了一个独立Looper的变量副本,使得每一个不同线程中的Looper相对独立互不影响
Looper
消息轮询器,它是一个死循环
每一个Looper对象都里面包含了一个MessageQueue
可以理解成使用死循环遍历MessageQueue中的Message,把适合的消息拿出来执行
Looper通过ThreadLocal与线程建立联系,在每一个线程中它都是一个单例,所以可以理解Looper是一个线程安全的单例
分析
Looper创建并与Thread关联
在ActivityThread的mian函数中
首先调用了Looper.prepareMainLooper(); 为主线程关联了一个Looper
然后调用Looper.loop();开始轮询;
刚才说了Looper是一个死循环,为什么会是死循环呢?因为在学Java的时候就知道,当mian函数执行完所有语句的时候就代表了程序结束,所有Looper在这里做死循环程序就不会退出。
我们可以推断如果让Looper退出死循环的话,我们的程序就退出了
myLooper() 是拿到当前线程对应的Looper单例
sThreadLocal是ThreadLocal的实例通过set方法将Looper与Thread关联,然后在任何地方通过sThreadLocal.get()可以拿到Thread中的Looper实例
Handler的创建
Handler在创建的时候会通过Looper.myLooper();方法拿到Thread中的Looper对象。如果线程中没有Thread对象Handler将会抛出异常
所以在子线程中使用Handler我们必须自己调用Looper.prepare();为这个子线程绑定Looper。然后调用Looper.loop();开始这个消息轮询器
Handler于Looper的关系
我们在使用mHandler.sendMessage()发送一个Message的时候,Handler会将Message和Message执行的时机(Message.when)添加到Looper中的MessageQueue中()。这样Looper在轮询的时候就会在合适的时机拿到这个Message并且执行。
Looper在拿到需要执行的Message的时候会调用Handler.dispatchMessage()方法执行Message。通过这个函数我们可以看出如果Message里面绑定了callback他会先直接执行这个callback而不会执行mCallback.handleMessage方法;这个callback实际上就是一个Runnable对象;
如果Handler中设置了mCallback他会拦截Handler的handleMessage方法;这相当于给Handler增加了一个事件拦截的机制。这个mCallback只能在通过Handler的构造函数传入
总结
通过分析Android的消息机制,我们可以知道我们传入Handler中的Message统统被放到了Looper的MessageQueue中。MessageQueue会在何时的时候发送这个Message给Looper,然后Looper将这个Message发送给Handler执行。
网友评论