在了解Handler原理的同时可以翻看源码研究一下Handler架构,下面是本人手写的Handler架构
Message.java
public class Message {
int what;
Handler target;
}
Message类我写的很简单,源码中是有很多代码的,这里能够传递值的参数只有what。target对象主要是为了最终能够执行到handleMessage回调方法,具体作用可以在下文代码中可以看到。
MessageQueue.java
/**
* 互斥队列的通用类
*/
public class MessageQueue {
//声明阻塞队列
private BlockingDeque blockingDeque = new LinkedBlockingDeque(50);
/**
* 入队(生产者)
* @param msg
* @return
*/
public void enqueueMessage(Message msg) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
try {
blockingDeque.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 出队(消费者)
* @return
*/
public Message next() {
Message msg = null;
try {
msg = (Message) blockingDeque.take();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
return msg;
}
}
MessageQueue类其实是最核心的地方了,这是一个消息队列,只有两种行文,出队和入队。并且,这是一个生产者、消费者设计模式。BlockingDeque是阻塞队列,在生产者、消费者设计模式中的运用比较常见。
Looper.java
public class Looper {
static MessageQueue mQueue;
private static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper() {
mQueue = new MessageQueue();
}
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static Looper myLooper() {
return sThreadLocal.get();
}
public static void loop(){
for(;;){
Message msg = mQueue.next();
if(msg == null){
continue;
}
msg.target.dispatchMessage(msg);
}
}
}
Looper中含有一个消息队列,looper只负责一个任务,那就是无限遍历消息队列,如果队列中有消息,就从队首取出消息,传递给handleMessage回调方法。这里的dispatchMessage方法就是为了执行Handler的回调方法handleMessage。
Handler.java
public class Handler {
private MessageQueue mQueue;
public Handler() {
Looper.prepare();
Looper looper = Looper.myLooper();
mQueue = looper.mQueue;
}
public void handleMessage(Message msg) {
}
public void dispatchMessage(Message msg){
handleMessage(msg);
}
public void sendMessage(Message msg){
MessageQueue queue = mQueue;
if (queue != null) {
enqueueMessage(queue, msg);
}
}
private void enqueueMessage(MessageQueue mQueue, Message msg){
msg.target = this;
mQueue.enqueueMessage(msg);
}
}
Handler负责将消息放进消息队列中,也就是所谓了入队了,sendMessage方法就是让消息入队。
Test.java
public class Test {
private static Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println(String.valueOf(msg.what));
}
};
public static void main(String[] args){
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<100;i++){
Message message = new Message();
message.what = i;
handler.sendMessage(message);
}
}
}).start();
Looper.loop();
}
}
Looper.loop()这个方法不能放入Activity的UI线程,否则会阻塞,这里我新建一个java的启动入口, 我们只需要执行main方法就可以了。
在底层中,ActivityThread是UI线程, Android的启动入口就是这个类的main方法,main方法中已经声明了Looper
Looper.prepareMainLooper();
Looper.loop();
图片.png
这是我再网上找的一张图, 流程还是比较清晰的。
需要注意的是:
消息入队和出队,必须在不同的线程中执行, 否则线程会阻塞。