作為一個Android開發(fā)人員 ,如果對android的消息處理機(jī)制不明白的話沟使,那就有點(diǎn)說不過去了青扔,至于有關(guān)消息處理機(jī)制在這里我就不多說了晓猛,各位請自行Google或者百度 栽连,不過我在這里還是總結(jié)一下有關(guān)消息處理機(jī)制的幾個類之間的關(guān)系:ToastUtil.showFailTop(error_message);
總結(jié)一下:
1.一個Thread只對應(yīng)一個Looper
2.一個Looper對象只對應(yīng)一個MessageQueue
3.一個MessageQueue對應(yīng)多個Messsage
4.一個Message只對應(yīng)一個Handler
所以上述結(jié)論是:一個Thread可以對應(yīng)多個Handler.
好了险领,上述大概都是大家都知道的,接下來我們就來說下大家不知道的。
先給大家描述一下這樣的一個情景:
你開啟了一個后臺線程 但是這個線程要往下執(zhí)行 必須等待另一個運(yùn)行在Hanlder線程下的Task的結(jié)果绢陌,得不到這個結(jié)果 你程序就無法往下進(jìn)行挨下,即使能往下進(jìn)行也沒有實(shí)際意義。此時你會想到如何解決這個問題呢下面?
你肯定想著我讓我當(dāng)前線程阻塞 ,然后呢等另一個線程上的任務(wù)完成后绩聘,通知我這個線程繼續(xù)往下運(yùn)行沥割,這就運(yùn)用到了Object上帝對象的wait 和 notifiy or notifyAll方法了。
其實(shí)Android系統(tǒng)中有很多這樣的一個場景凿菩,我隨便舉個例子來給大家說明一下:
這就是Android系統(tǒng)系統(tǒng)systemserver進(jìn)程的時候所調(diào)用的一行代碼机杜,這個函數(shù)的邏輯很清楚 ,就是初始化一個WindowManagerService實(shí)例對象衅谷,但是這里運(yùn)用了一個Handler的一個技巧椒拗,那就是只有當(dāng)runWithScissors方法中的Runnable任務(wù)執(zhí)行完成后,也就是WindowManagerService構(gòu)造完成之后才能返回获黔,否則如果連最重要的WMS都沒有初始化成功 蚀苛,那么Android系統(tǒng)就沒有繼續(xù)進(jìn)行下去的理由了,那么我們就來看下這里具體是如何實(shí)現(xiàn)的玷氏。
我們來看重點(diǎn) ?:第三個if判斷條件 ?其實(shí)就是判斷 我們當(dāng)前運(yùn)行的線程是否跟Handler所在的線程一致 堵未,如果一致的話 那么就世界運(yùn)行Runnable的run方法 ?如果不是 那么就要涉及到等待喚醒機(jī)制了 ?而這個機(jī)制就是靠BlockingRunnable來實(shí)現(xiàn)的,我們來看下具體的實(shí)現(xiàn)代碼:
核心代碼就是這個 盏触,我們看到 首先就是將任務(wù)添加到Hanlder對應(yīng)的MessageQueue隊(duì)列中去渗蟹,如果添加成功才繼續(xù)往下運(yùn)行,
這里我們只考慮添加成功的情況:
?然后進(jìn)入到了同步代碼塊中:
? ?我們看到有一個while循環(huán)赞辩,并且標(biāo)志位是一個mDone 這是BlockingRunnable的一個成員變量 ?默認(rèn)值是false ?我們發(fā)現(xiàn)這里的代碼的邏輯就是如果任務(wù)添加成功 然后就在該對象監(jiān)視器(this)上阻塞 雌芽,直到被喚醒。 那么我們猜想一下肯定是mDone的值影響到了代碼的邏輯 辨嗽,我們看下這個值是如何被改變的世落。
我們看到了 只有當(dāng)run方法運(yùn)行完成之后 ?然后才會去設(shè)置mDone的值 然后通知阻塞到該監(jiān)視器上的線程 ?,這樣就做到了 一個后臺線程需要等待另一個線程的執(zhí)行結(jié)果的時候的一種方式 ?我相信很多人不看源碼的話 是不會知道有這么個技巧的糟需,但是這個方法是HIDE的 如果我們想要實(shí)現(xiàn)類似的邏輯的話 我們就要使用反射 來進(jìn)行岛心,大家盡量不要濫用 ,一定要考慮清楚自己的場景之后 結(jié)合實(shí)際去選擇合適的方法 篮灼,這里我貼一下我反射的代碼 :
handler=newHandler() {
@Override
public?voidhandleMessage(Messagemsg)?{
super.handleMessage(msg);
}
};
Log.e("FormalCourseFrag","阻塞方法開始執(zhí)行--"+SystemClock.elapsedRealtime());
Classc;
Methodmethod;
try{
Class[]argsClass=newClass[2];
argsClass[0]=Runnable.class;
argsClass[1]=long.class;
Object[]params=newObject[2];
params[0]=newRunnable()?{
@Override
public?voidrun()?{
try{
Thread.sleep(10000);
}catch(InterruptedExceptione)?{
e.printStackTrace();
}
}
};
params[1]=0;
c=Class.forName("android.os.Handler");
method=c.getMethod("runWithScissors",argsClass);
method.invoke(handler,params);
}catch(ClassNotFoundExceptione)?{
e.printStackTrace();
}catch(NoSuchMethodExceptione)?{
e.printStackTrace();
}catch(InvocationTargetExceptione)?{
e.printStackTrace();
}catch(IllegalAccessExceptione)?{
e.printStackTrace();
}