本文沒有那麼多的廢話,直接看代碼:
此爲AsyncQueryHandler的構造方法
public AsyncQueryHandler(ContentResolver cr) {
super();
mResolver = new WeakReference<ContentResolver>(cr);
synchronized (AsyncQueryHandler.class) {
if (sLooper == null) {
HandlerThread thread = new HandlerThread("AsyncQueryWorker");
thread.start();
//需要注意的是此getLooper()方法在HandlerThread類中是同步等待獲取run()方法中prepare()準備的線程相關的Looper對象,
// 也就是說分線程準備好了looper以後,在此線程中纔可以得到
sLooper = thread.getLooper();
}
}
mWorkerThreadHandler = createHandler(sLooper);
}
在AsyncQueryHandler構造中new出來 的HandlerThread繼承了Thread 在其的run方法中創建 了個Looper輪詢器,並阻塞調用.loop方法在那不停的輪詢這個內部開啓的工作線程的隊列. 在這內部開啓的線程中獲得了這個線程綁定的輪詢器., 用這個輪詢器創建了一個WorkerHandler的mWorkerThreadHandler變量的Handler ,
由於此Handler在創建時接收了這個開啓的線程的輪詢器 , 那這個Handler就相當於在這個線程中創建的,自然它的handeMessage方法將會運行在這個線程中執行,
這也就是這個AsyncQueryHandler的特別之處, 其中有兩個handleMessage方法 , 要記住:AsyncQueryHandler的handleMessage方法是主線程中運行的, 而WorkerThreadHandler的handleMessage方法是在構造方法中創建的一個線程中執行的, 只不過它的代碼被放到這個類中了. 爲什麼呢? 我看到這個handlerMessage方法的代碼中用到了ContentResolver對象,此對象是從UI主線程中傳過來的, 所以放在這不用傳給那個開啓的線程也是未嘗不可的.
在這個handleMessage中最終是將執行的結果cursor通過Message回覆到AsyncQueryHander這個類的handlerMessage中執行,在其中解析msg並根據event判斷操作類型(CRUD)來執行AsyncQueryHandler的回調方法.
所以我們在主線程中實現這個AsyncQueryHandler類的時候可以選擇性的重寫這四個protected修飾的on….Complete完成方法來做一些數據操作完成後的操作.
整個異步查詢的操作其時就是AsyncQueryHandler類內部的兩個handleMessage之間交互的過程.
入口就是start開頭的CRUD操作,在這些start方法中只是把參數用一個Message封裝起來調用那個構造中創建的子線程的輪詢器的Handler對象(mWorkerThreadHandler).的sendMessage()方法來發送的
在WorkerHandler的handleMessage方法中收到解析執行這個用戶封裝的msg中的內容, 並將結果又返回給AsyncQueryHandler這個HandleMessage方法在其中回調用戶實現的on…Complete方法完成數據的後續處理.
以下爲部分源碼
protected class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(looper); //看此處使用了looper
}
public void handleMessage(Message msg) {
final ContentResolver resolver = mResolver.get();
if (resolver == null) return;
WorkerArgs args = (WorkerArgs) msg.obj;
int token = msg.what;
int event = msg.arg1;
switch (event) {
case EVENT_ARG_QUERY:
Cursor cursor;
//..............CRUD操作
args.result = cursor;
}
Message reply = args.handler.obtainMessage(token);///回覆msg
reply.obj = args;
reply.arg1 = msg.arg1;
reply.sendToTarget(); //回覆
=============
public void startQuery(int token, Object cookie, Uri uri,
String[] projection, String selection, String[] selectionArgs,
String orderBy) {
// Use the token as what so cancelOperations works properly
Message msg = mWorkerThreadHandler.obtainMessage(token);
msg.arg1 = EVENT_ARG_QUERY;
WorkerArgs args = new WorkerArgs();
args.handler = this;
args.uri = uri;
args.projection = projection;
args.selection = selection;
args.selectionArgs = selectionArgs;
args.orderBy = orderBy;
args.cookie = cookie;
msg.obj = args;
mWorkerThreadHandler.sendMessage(msg);//此處是向開啓的那個線程中的handler發送 消息
=====================
public class HandlerThread extends Thread {
public void run() {
mTid = Process.myTid();
Looper.prepare(); //由於 不是在主線程中WorkerHandler中包含的這個Looper對象必須手動的調用prepare來準備好(另附:looper是線程本地化的)
synchronized (this) {
mLooper = Looper.myLooper(); //獲得當前線程的輪詢器
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); ///阻塞 方法, 不斷的從隊列中取消息.
mTid = -1;
}
如有理解錯誤和不準確的地方,還請一定要回復...