本文没有那么多的废话,直接看代码:
此为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;
}
如有理解错误和不准确的地方,还请一定要回复...