基于上篇文章研究了handler的源码(handler核心原理),自己想手动写下handler实现原理代码,项目结构如下:,自己写了个单元测试来模拟ActivityThread的启动,下面是ActivityThread中的main测试方法;
@Test
public void main(){
//创建looper
Looper.prepare();
//handler处理消息
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println( msg.obj.toString());
}
};
//子线程发送消息给messagequeue
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
msg.obj = "handlerlocal";
handler.sendMessage(msg);
}
}).start();
//轮训,取出消息给handler处理
Looper.loop();
}
下面分别是上面几个类的代码:
public class Handler {
public static MessageQueue mQueue;
public Handler() {
Looper looper = Looper.myLooper();
mQueue = looper.mQueue;
}
//将message 消息存放到messagequeue中
public void sendMessage(Message msg) {
enqueueMessage(msg,mQueue);
}
private void enqueueMessage(Message msg, MessageQueue mQueue) {
msg.target = this; //把handler赋值给了message.target,后面(loop())dispatchMessage就是用的这个handler对象
mQueue.enqueueMessage(msg);
}
public void dispatchMessage(Message msg) {
handleMessage(msg);
}
public void handleMessage(Message msg){
}
}
public class Looper {
private static ThreadLocal<Looper> threadLocal = new ThreadLocal<>();
public static MessageQueue mQueue;
private Looper(){
mQueue = new MessageQueue();
}
public static void prepare() {
if (threadLocal.get() != null) {
new RuntimeException("not init looper agin"); //这样设计为了保证looper的唯一性
}
threadLocal.set(new Looper()); //绑定当前线程(主线程)和looper
}
public static void loop() {
while (true){ //死循环从阻塞队列中取出message交给handler处理
Message msg = mQueue.next();
msg.target.dispatchMessage(msg);
}
}
public static Looper myLooper() {
return threadLocal.get();//handler中会调用这个方法取出messagequee对象,把message存放到messagequeue中
}
}
public class Message {
public Handler target;
public Object obj;
@Override
public String toString() {
return obj.toString();
}
}
public class MessageQueue {
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<>(50);
public void enqueueMessage(Message msg) {
try {
blockingQueue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Message next() {
try {
Message msg = blockingQueue.take();
return msg;
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}