在了解Handler原理的同时可以翻看源码研究一下Handler架构,下面是本人手写的Handler架构
Message.javapublic 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.javapublic class Looper { static MessageQueue mQueue; private static ThreadLocal sThreadLocal = new ThreadLocal(); 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.javapublic 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.javapublic 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方法中已经声明了LooperLooper.prepareMainLooper();Looper.loop();
图片.png
作者:NoBugException
链接:https://www.jianshu.com/p/92c8495c6ab1