【安卓笔记】AsyncQueryHandler源码剖析

AsyncQueryHandler类用于提供异步数据库操作(增删改查)功能。本文视图从源码角度分析这个类。

1.AsyncQueryHandler使用方式:
AsyncQueryHandler handler = new AsyncQueryHandler(this.getContentResolver())
		{
			@Override
			protected void onQueryComplete(int token, Object cookie,Cursor cursor)
			{
			}
			@Override
			protected void onUpdateComplete(int token, Object cookie, int result)
			{
			}
			@Override
			protected void onInsertComplete(int token, Object cookie, Uri uri)
			{
			}
			@Override
			protected void onDeleteComplete(int token, Object cookie, int result)
			{
			}
		};
		handler.startQuery(token, cookie, uri, projection, selection, selectionArgs, orderBy);
		handler.startDelete(token, cookie, uri, selection, selectionArgs);
		handler.startInsert(token, cookie, uri, initialValues);
		handler.startUpdate(token, cookie, uri, values, selection, selectionArgs);

2.源码分析

分析源码前,从整体上把握这个类:每个AsyncQueryHandler对象都会开启一个后台线程,在线程中执行与ContentProvider组件的数据交互,进行增删改查。调用时,可以通过AsyncQueryHandler.startXXX系列方法将请求打包发送到后台线程,当相关处理完成后,会将结果异步回传给主线程并调用AsyncQueryHandler.onXXXComplete方法通知调用者。调用者每次请求时,需要传入一个整型值token作为这次请求的标识,当该请求完成后进行回调时,会将token传回,帮助调用者确定这是哪一次请求。


AsyncQueryHandler是个抽象类,不能直接被实例化,这点需要注意:

public abstract class AsyncQueryHandler extends Handler

其内部封装了Looper和Handler,这个消息循环工作在子线程。另提供4个常量标识当前操作类型。ContentResolver由构造器注入。
 private static final int EVENT_ARG_QUERY = 1;
    private static final int EVENT_ARG_INSERT = 2;
    private static final int EVENT_ARG_UPDATE = 3;
    private static final int EVENT_ARG_DELETE = 4;
    /* package */ final WeakReference<ContentResolver> mResolver;
    private static Looper sLooper = null;
    private Handler mWorkerThreadHandler;

工作线程的handler,即mWorkThreadHandler的handleMessage方法负责操作数据库:
 protected class WorkerHandler extends Handler {
        public WorkerHandler(Looper looper) {
            super(looper);
        }
        @Override
        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;
                    try {
                        cursor = resolver.query(args.uri, args.projection,
                                args.selection, args.selectionArgs,
                                args.orderBy);
                        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;
                case EVENT_ARG_INSERT:
                    args.result = resolver.insert(args.uri, args.values);
                    break;
                case EVENT_ARG_UPDATE:
                    args.result = resolver.update(args.uri, args.values, args.selection,
                            args.selectionArgs);
                    break;
                case EVENT_ARG_DELETE:
                    args.result = resolver.delete(args.uri, args.selection, args.selectionArgs);
                    break;
            }
            //将结果返回给AsyncQueryHandler的handleMessage处理
            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();
        }
    }

AsyncQueryHandler在构造的时候,会创建一个HandlerThread,start之,然后获取其Looper,并利用其Looper构建子线程消息循环,并与mWorkThreadHandler绑定:
  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);
    }
这个类提供了WorkerArgs封装数据库操作的请求参数:
 protected static final class WorkerArgs {
        public Uri uri;
        public Handler handler;
        public String[] projection;
        public String selection;
        public String[] selectionArgs;
        public String orderBy;
        public Object result;
        public Object cookie;
        public ContentValues values;
    }

当外界调用startXXX方法时,其实会构造WorkerArgs对象,然后将这个对象以消息的形式发送给mWorkThreadHandler  
,处理完成后将结果发送给AsyncQueryHandler本身:
startXXX:
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;//注意这行制定了Handler为本身,即AsyncQueryHandler
        args.uri = uri;
        args.projection = projection;
        args.selection = selection;
        args.selectionArgs = selectionArgs;
        args.orderBy = orderBy;
        args.cookie = cookie;
        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);//交给子线程处理
    }

WorkerHandler:
 Message reply = args.handler.obtainMessage(token);
            reply.obj = args;
            reply.arg1 = msg.arg1;
   ...
          reply.sendToTarget();//在startXXX方法中已经制定了target为AsyncQuertHandler本身
最终,操作结果交由AsyncQueryHandler类的handleMessage处理:
  @Override
    public void handleMessage(Message msg) {
        WorkerArgs args = (WorkerArgs) msg.obj;
        if (localLOGV) {
            Log.d(TAG, "AsyncQueryHandler.handleMessage: msg.what=" + msg.what
                    + ", msg.arg1=" + msg.arg1);
        }
        int token = msg.what;
        int event = msg.arg1;
        // pass token back to caller on each callback.
        switch (event) {
            case EVENT_ARG_QUERY:
                onQueryComplete(token, args.cookie, (Cursor) args.result);
                break;
            case EVENT_ARG_INSERT:
                onInsertComplete(token, args.cookie, (Uri) args.result);
                break;
            case EVENT_ARG_UPDATE:
                onUpdateComplete(token, args.cookie, (Integer) args.result);
                break;
            case EVENT_ARG_DELETE:
                onDeleteComplete(token, args.cookie, (Integer) args.result);
                break;
        }
    }
AsyncQueryHandler类的handleMessage方法回调了onXXXcomplete系列方法。我们重写onXXXcomplete方法即可拿到数据库操作结果。


这个设计太赞了!!!!







郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。