基於上篇文章研究了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;
}
}