android_AsyncQueryHandler的理解_2011-10-26

本文没有那么多的废话,直接看代码:

此为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;
    }


如有理解错误和不准确的地方,还请一定要回复...

发布了18 篇原创文章 · 获赞 1 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章