此为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;
- }
如有理解错误和不准确的地方,还请一定要回复...