緩緩飄落的楓葉像思念
當(dāng)弄明白了Handler機(jī)制實(shí)現(xiàn)的原理后并鸵,自己動(dòng)手實(shí)現(xiàn)一下消息在線程間切換是很簡(jiǎn)單的事情。
首先我們先來(lái)明確一下Handler機(jī)制中需要用到的類
- Handler類侠驯。Handler類負(fù)責(zé)關(guān)聯(lián)當(dāng)前線程的Looper和MessageQueue,以及發(fā)送消息到MessageQueue中,還有一個(gè)消息處理的回調(diào)周瞎。
public class MyHandler {
private MyMessageQueue messageQueue;
// 獲取Looper與消息隊(duì)列
public MyHandler(){
MyLooper myLooper = MyLooper.myLooper();
messageQueue = myLooper.getMessageQueue();
}
// 分發(fā)消息
public void dispatchMessage(MyMessage msg){
handleMessage(msg);
}
// 發(fā)送消息
public void sendMessage(MyMessage message) {
// 將當(dāng)前的Handler對(duì)象賦值給了message的target黄琼,
message.target = this;
messageQueue.addMessage(message);
}
public void handleMessage(MyMessage msg) { }
}
- Looper有兩個(gè)最主要的方法樊销,prepare()和loop()。prepare()方法創(chuàng)建了一個(gè)Looper對(duì)象脏款,并存入ThreadLocal對(duì)象中围苫。loop()從消息隊(duì)列中不停的取出Message,通過(guò)Message.target回調(diào)給處理的Handler撤师。此外剂府,Looper還創(chuàng)建了MessageQueue,以及MessageQueue的獲取方式剃盾。
public class MyLooper {
private static ThreadLocal<MyLooper> threadLocal = new ThreadLocal<>();
public static MyMessageQueue messageQueue;
private MyLooper(){
messageQueue = new MyMessageQueue();
}
public MyMessageQueue getMessageQueue(){
return messageQueue;
}
/**
* 獲取當(dāng)前線程的looper
*/
public static MyLooper myLooper(){
MyLooper myLooper = threadLocal.get();
return myLooper;
}
// 給當(dāng)前線程創(chuàng)建一個(gè)相關(guān)聯(lián)的Looper對(duì)象腺占,并存在ThreadLocal當(dāng)中
public static void prepare(){
if(threadLocal.get() != null){
throw new RuntimeException("Current Thread is created looper");
}else{
threadLocal.set(new MyLooper());
}
}
public static void loop(){
MyLooper myLooper = threadLocal.get();
while(true){
List<MyMessage> msgList = myLooper.messageQueue.getMsgList();
for(int i = 0; i < msgList.size(); i++){
MyMessage myMessage = msgList.get(i);
myMessage.target.dispatchMessage(myMessage);
msgList.remove(msgList.get(i));
}
}
}
}
- Message類就很簡(jiǎn)單了。只有一個(gè)Handler類型的引用万俗,然后what和存儲(chǔ)數(shù)據(jù)的obj湾笛。
public class MyMessage {
public MyHandler target;
public int what;
public Object obj;
}
- MessageQueue中也只是維護(hù)了一個(gè)隊(duì)列。闰歪、
public class MyMessageQueue {
private List<MyMessage> msgList = new ArrayList<MyMessage>();
public void addMessage(MyMessage msg){
msgList.add(msg);
}
public List<MyMessage> getMsgList(){
return msgList;
}
}
- 測(cè)試
public class MainActivity extends AppCompatActivity {
private MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
MyLooper.prepare();
mHandler = new MyHandler(){
@Override
public void handleMessage(@NonNull MyMessage msg) {
if(msg.what == 0x111){
Log.e("thread1",msg.obj.toString() );
}
}
};
MyLooper.loop();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
MyMessage message = new MyMessage();
message.what = 0x111;
message.obj = "哎呀媽呀嚎研,都特么開始手寫Handler了,牛逼牛逼库倘!";
mHandler.sendMessage(message);
try{
Thread.sleep(2000);
}catch (Exception ee){
ee.printStackTrace();
}
}
});
thread1.start();
try{
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
thread2.start();
}
}
image.png
測(cè)試后临扮,可以看到消息確實(shí)是從thread2發(fā)送給了thread1。手寫Handler完美成功教翩。
但是我們這里有一個(gè)問(wèn)題杆勇,就是Thread1收到一次消息后,如果再在Thread2里面發(fā)送一次消息饱亿,Thread1就收不到消息了蚜退。因?yàn)門hread1的線程已經(jīng)執(zhí)行完了,Handler對(duì)象也就被銷毀了彪笼。
我們平常用的Handler都是接收了一個(gè)消息之后钻注,還是可以繼續(xù)接收的。因?yàn)槲覀儎?chuàng)建Handler的時(shí)候是在主線程創(chuàng)建的配猫,而主線程是一直運(yùn)行的幅恋,不會(huì)死掉的,直到我們退出APP泵肄。