一殴胧、概述
AsyncQueryHandler
方便了我們對ContentProvider
進行增渗稍、刪、改团滥、查竿屹,此外,我們通過學習它的原理可以更好地理解HandlerThread
灸姊,學習如何在項目中使用它拱燃。
二、源碼
AsyncQueryHandler
中的關(guān)鍵是mWorkerThreadHandler
力惯,它在其handleMessage
中進行操作碗誉,因為它在構(gòu)造時傳入的Looper
所關(guān)聯(lián)的Thread
并不是主線程,因此所有在handleMessage
中的操作都是異步的父晶,這個變量的初始化時在其構(gòu)造函數(shù)中:
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
才會生成哮缺,因此當我們采用默認實現(xiàn)時,并且在多個地方實例化不同的AsyncQueryHandler
對象甲喝,每個對象對應的是不同的WorkerHandler
尝苇,但是 WorkerHandler
關(guān)聯(lián)到的是同一個Looper
,我們通過它執(zhí)行的所有任務是放在一個隊列當中順序執(zhí)行的。如果我們不希望運行在默認的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;
}
}
當我們調(diào)用了插入方法之后侮东,整個過程如下:
-
mWorkerThreadHandler
發(fā)送一條消息,該消息當中帶有插入相關(guān)的所有參數(shù)以及AsyncQueryHandler
子類的實例豹芯。 - 在
mWorkderThreadHanlder
的handleMessage
中悄雅,它調(diào)用ContentResolver
的對應插入方法進行插入,它和mWorkderThreadHandler
關(guān)聯(lián)的Looper
是運行在同一個線程當中的铁蹈。 - 插入完畢之后宽闲,通過消息當中傳入的
AsyncQueryHandler
子類的實例將執(zhí)行的結(jié)果發(fā)送回去,在其AsyncQueryHandler
的handleMessage(Message message)
方法中握牧,回調(diào)抽象方法onInsertComplete(token, args.cookie, (Uri) args.result)
容诬,子類通過實現(xiàn)該方法來獲取執(zhí)行的結(jié)果。