編輯:Android開發實例
今天晚上研究了一下啊AsyncQueryHandler,收獲挺大,記錄下重要知識點,以後繼續補充研究。
研究AsyncQueryHandler這個類的時候遇到了幾個重要的不清楚的知識點
1. Handler與Thread,Looper的關系
2. HandlerThread是干什麼用的
3. ThreadLocal類是干什麼用的
Handler主要是用來發送和處理消息,但是發送了消息後,消息是怎麼傳遞的呢?這就是Looper的作用了,每個Handler中都會有一個Looper對象,如果在創建Handler的時候不指定,系統就會默認將當前線程的Looper綁定到Handler上,Looper對象中維護者一個消息隊列,Hander發送的消息都會存儲到這個消息隊列中,Looper不斷的遍歷這個消息隊列,取出消息,交給handleMessage方法處理。Looper屬於哪個線程,hadleMessage方法就會在那個線程中執行。
HandlerThread不但能提供異步處理,Handler處理消息的方法也會在這個線程中執行,他最要的作用就是提供了一個線程。(這個類還有待研究)
ThreadLocal類主要是用來多個模塊共享變量用的,但是不同線程之間的變量的值卻不相同。
說明1:對象a,對象b比如說是某個類的實例對象,在模塊A,B,C中共享對象a,還有對象b,在線程A中,模塊A中設置a的值,在模塊B,C中取出a的值,三個模塊操作的是同一個值,但是對象a和對象b分別屬於兩個線程,他們是不同的。
AsyncQueryHandler的工作機制是什麼?
AsyncQueryHandler繼承了Handler對象,但是他提供的構造方法中卻沒有Looper參數,也就是說他和他所在的當前線程綁定,AsyncQueryHandler內部有一個Hhandler對象,叫mWorkerHandler,他和一個HandlerThread綁定,mWorkerHandler負責將打包好的消息發送,並且處理,並將結果作為消息發送給AsyncQueryHandler。他是怎麼發送的?AsyncQueryHandler內部有一個WorkerArgs完美類,他封裝了startAsyncQuery等方法的參數,並且通過這行代碼
WorkerArgs args = new WorkerArgs();
args.handler = this;將當前Handler封裝進去,發送到HandlerThread中去,mWorkerHandler處理完消息得到結果後,args.handler將結構發送給自己進行處理。(這就是線程間的通信了)
mWorkerHandler和一個子線程綁定,能夠處理比較耗時的操作,AsyncQueryHandler提供異步處理。
總結:
Handler有兩個作用,Handler用在一個線程中,就是實現異步操作。用在不同的線程之間,那就是異步操作加線程間通信。
補充:
HandlerThread:
先看他的類描述:Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
這是一個包含了Looper對象的線程,這個looper可以用來創建Handler對象,記住:start()方法必須被調用,否則通過getLooper方法得到的looper對象是空的。通過調用start方法,就會去執行該線程的run方法, public void run() {
mTid = Process.myTid();
Looper.prepare();//創建一個Looper實例,並且存儲在ThreadLocal中,ThreadLocal中維護一個HashMap,鍵是線程號
synchronized (this) {
mLooper = Looper.myLooper();//得到當前線程的Looper,就是剛才perpare方法中創建並存儲的那個Looper實例
Process.setThreadPriority(mPriority);
notifyAll();
}
onLooperPrepared();
Looper.loop();//開始輪詢
mTid = -1;
}
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
AsyncQueryHandler是如何提供onxxxComplete方法給用戶,由用戶自己實現的?
public abstract class AsyncQueryHandler extends Handler 他是一個抽象類
MessageQueue是不是一個任務隊列?
是,他是一個優先級隊列(可以通過ArrayList的排序來實現)。它內部自己維護一個ArrayLsit集合,用來存儲Message消息,Message消息有三種,普通消息,按照先發送先執行的FIFO原則進行;高優先級的消息,這種消息會直接插在隊列的最前面,立刻執行;還有一種定時消息,類似於定時任務,到時間才執行。
Looper是如何輪詢MessageQueue的?
當在主線程中使用Handler的時候,不用指定Looper,因為在主線程開啟的時候,就已經調用了Looper.loop()方法開始輪詢了。
擋在子線程中使用Handler的時候,通過調用Looper的prepare方法創建存儲Looper對象,還得調用Looper.loop()方法開啟輪詢。
當配合HandlerThread使用Handler的時候,HandlerThread的run方法中調用了Looper.loop()方法。
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
}
Message消息實現了Parcelable接口
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
BroadcastReceiver 是系統全局廣播監聽類, 其主要方法是onReceive(),自定義的廣播類繼承於它並實現自己的onReceive()處理邏輯B
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用