一、概述
AsyncQueryHandler
方便了我們對ContentProvider
進行增、刪、改、查,此外,我們通過學習它的原理可以更好地理解HandlerThread
,學習如何在專案中使用它。
二、原始碼
AsyncQueryHandler
中的關鍵是mWorkerThreadHandler
,它在其handleMessage
中進行操作,因為它在構造時傳入的Looper
所關聯的Thread
並不是主執行緒,因此所有在handleMessage
中的操作都是非同步的,這個變數的初始化時在其建構函式中:
public AsyncQueryHandler(ContentResolver cr) {
super();
mResolver = new WeakReference<ContentResolver>(cr);
synchronized (AsyncQueryHandler.class) {
if (sLooper == null) {
HandlerThread thread = new HandlerThread("AsyncQueryWorker");
thread.start();
sLooper = thread.getLooper();
}
}
mWorkerThreadHandler = createHandler(sLooper);
}
protected Handler createHandler(Looper looper) {
return new WorkerHandler(looper);
}
複製程式碼
可以看到sLooper
只有在第一次例項化AsyncQueryHandler
才會生成,因此當我們採用預設實現時,並且在多個地方例項化不同的AsyncQueryHandler
物件,每個物件對應的是不同的WorkerHandler
,但是 WorkerHandler
關聯到的是同一個Looper
,我們通過它執行的所有任務是放在一個佇列當中順序執行的。如果我們不希望執行在預設的Looper
中,那麼也可以通過重寫createHandler
來傳入一個另外的 Looper。因為AsyncQueueHandler
的增、刪、改、查的原理都是相同的,因此我們單獨看一下增加的操作,就可以理解它的思想了:
public final void startInsert(int token, Object cookie, Uri uri, ContentValues initialValues) {
Message msg = mWorkerThreadHandler.obtainMessage(token);
msg.arg1 = EVENT_ARG_INSERT;
WorkerArgs args = new WorkerArgs();
args.handler = this;
args.uri = uri;
args.cookie = cookie;
args.values = initialValues;
msg.obj = args;
mWorkerThreadHandler.sendMessage(msg);
}
protected class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(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_INSERT:
args.result = resolver.insert(args.uri, args.values);
break;
}
Message reply = args.handler.obtainMessage(token);
reply.obj = args;
reply.arg1 = msg.arg1;
reply.sendToTarget();
}
}
@Override
public void handleMessage(Message msg) {
WorkerArgs args = (WorkerArgs) msg.obj;
int token = msg.what;
int event = msg.arg1;
switch (event) {
case EVENT_ARG_INSERT:
onInsertComplete(token, args.cookie, (Uri) args.result);
break;
}
}
複製程式碼
當我們呼叫了插入方法之後,整個過程如下:
mWorkerThreadHandler
傳送一條訊息,該訊息當中帶有插入相關的所有引數以及**AsyncQueryHandler
子類的例項**。- 在
mWorkderThreadHanlder
的handleMessage
中,它呼叫ContentResolver
的對應插入方法進行插入,它和mWorkderThreadHandler
關聯的Looper
是執行在同一個執行緒當中的。 - 插入完畢之後,通過訊息當中傳入的
AsyncQueryHandler
子類的例項將執行的結果傳送回去,在其AsyncQueryHandler
的handleMessage(Message message)
方法中,回撥抽象方法onInsertComplete(token, args.cookie, (Uri) args.result)
,子類通過實現該方法來獲取執行的結果。