在阅读本文前请务必对android的handler、message、looper、的关系具有相当的认识。这里强烈推荐一位大神的的博客: Android异步消息处理机制详解及源码分析。这里我就默认你已近了解android的message消息传递机制了。那么我们就开始研究我们的AsyncQueryHandler
研究类一般都是先从构造函数进入。那么我们先来看我们构造函数
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);
}
我们首先看到的是新建一个handlerthread的对象,这里的thread没有老刘句柄,如果正常情况下,这个类是会消失的,但是这里立从中获得一个looper对象,这里的looper是做为workerthread的handler的构造参数。从而mWorkerThreadHandler 拥有了thread的句柄,因此thread不会被系统回收,并且workerthread的messageque。因此我们可以在主线程中发消息给workthread消息,这里我们获取了所应该有的所有对象,包括workthread,和主线程的handler(ps:AsyncQueryHandler本身就handler),这里基本难点都得到解决。下面就看大概其他具体应用。应用当然是查询数据库了。当然会从startQuery()
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);
}
这里除了token貌似是为了获取同一类的message而传递的一个特定参数。是为了优化,其他ContentResolver 的传递参数。至于arg1是传递了动作的参数。然后通过mWorkerThreadHandler 接受处理,当然是在workerthread里面,这里其他的删除插入查询都是这种模式实现的,当然我们都知道我们查询完毕后是如何获得消息的,那么我们追workthreadhanler的处理方法。这里我们选择workhandler的handleMessage()处理查询方法的的一段代码。
case EVENT_ARG_QUERY:
Cursor cursor;
try {
cursor = resolver.query(args.uri, args.projection,
args.selection, args.selectionArgs,
args.orderBy);
// Calling getCount() causes the cursor window to be filled,
// which will make the first access on the main thread a lot faster.
if (cursor != null) {
cursor.getCount();
}
} catch (Exception e) {
Log.w(TAG, "Exception thrown during handling EVENT_ARG_QUERY", e);
cursor = null;
}
args.result = cursor;
break;
查询当然在这里,至于如何处理我们当然继续追踪这个函数。在switch外面会看到这样一段代码:
Message reply = args.handler.obtainMessage(token);
reply.obj = args;
reply.arg1 = msg.arg1;
if (localLOGV) {
Log.d(TAG, "WorkerHandler.handleMsg: msg.arg1=" + msg.arg1
+ ", reply.what=" + reply.what);
}
reply.sendToTarget();
很明确我们把我们的cursur给封装在了relpay这个message中,我们都知道args是在主线程中实例化的。当然handler是在和message是主线程中message。所以
reply.sendToTarget();
当然是吧我们的消息发送给主线程中处理。这里本来应该是贴上主线程的代码的,但是感觉没啥难度,仅
仅是调用了查询玩成功后的接口,当然这里我们要想获取这个查询完毕,只能靠这个接口来监听cursor
查询完毕。到这里这个类搞定了。