AsyncQueryHandler

在阅读本文前请务必对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
查询完毕。到这里这个类搞定了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值