AsyncQueryHandler详解及使用

AsyncQueryHandler概述

项目中,用到了AsyncQueryHandler,所以在这里将自己对它的理解写出来,做一个总结。如果有错误的地方,或者理解不到位的地方,请各位高手批评指正~

AsyncQueryHandler是一个抽象类,主要是用来在异步线程中访问数据库,当访问结束后通知界面更新。不过,可千万不要以为AsyncQueryHandler只是用于异步查询数据库哦(虽然这个抽象类名的字面含义是“异步查询”),看过其实现源码就知道,它能做到对数据库进行异步的增删改查。

AsyncQueryHandler实现原理

我们来通过源码看一下,AsyncQueryHandler究竟是如何实现异步操作数据库的功能的。

AsyncQueryHandler是一个抽象类,继承自Handler,它的构造函数是这样的:

构造函数中,主要是判断当前类中的静态Looper对象是否为null,如果为空,就新建一个HandlerThread,并获得sLooper;如果不为空,就利用这个sLooper,新建一个Handler。由此可知,新建的handler就是在异步线程的。

我们再来看createHandler方法:

由此可知,AsyncQueryHandler的构造函数,主要做的,就是在异步线程中创建了一个WorkHandler对象。那么,这个WorkHandler又是一个什么样的类呢?其实,它就是一个普通的Handler的子类,我们主要来看它的handlerMessage方法:

我们可以看到,AsyncQueryHandler将对数据库的增删改查操作放到了WorkHandler的handlerMessage方法中。也就是说,AsyncQueryHandler将对数据库的操作放在了WorkHandler对象所在的异步线程中了。另外,在handlerMessage方法的最后,又将数据库操作结果封装到Message对象中,通过这个Message对象将操作结果再一次发出去。至于这个Message对象,我们下面结合一系列startXXX方法来说。(XXX代表Query/Insert/Update/Delete)

我们平时在用AsyncQueryHandler的时候,是先继承AsyncQueryHandler类,并实现其onXXXComplete方法。然后在使用的时候,startXXX就可以了。那么这个startXXX又做了什么呢?我们以startQuery方法来说:

在startQuery方法中,将该方法的参数都放进了args对象中,而且,要注意到的是,arg.handler=this,也就是说,将AsyncQueryHandler这个类对象本身也放进了args对象中。然后,将args对象放进msg对象中,通过构造函数产生的mWorkerThreadHandler发送出去。根据Handler的基本知识,我们知道,这个msg就被传入了WorkHandler类的handlerMessage方法中,然后就可以根据传进来的参数,执行对应的查询操作啦。现在,我们就可以解释WorkHandler的handlerMessage方法所产生的Message对象了。还是看一下WorkHandler中handlerMessage的代码:

我们可以看到,Message对象就是通过startQuery中传入的handler得到的,也就是AsyncQueryHandler对象本身,那么,这个消息最后通过sendToTarget方法发送出去,去承接这个消息的方法就一定是AsyncQueryHandler的handlerMessage方法了!哈哈,也就是说,这样就能够把异步操作数据库的结果传到主线程来进行处理了~

我们来看一下AsyncQueryHandler的handlerMessage方法:

在AsyncQueryHandler的handlerMessage中,调用onQueryComplete方法,就可以完成界面的一些更新以及其它不耗时操作啦。

总的来说,AsyncQueryHandler就是用了在不同线程中的handler来实现异步访问数据库的功能的。为了更好地理解,我把它的工作过程归纳为下图:

AsyncQueryHandler的使用

很简单,就两步:

继承AsyncQueryHandler类,并实现onXXXComplete方法。

onXXXComplete方法中主要是处理数据库操作结果,用以完成界面更新。如果不处理结果的话,也可以不实现onXXXComplete方法。

利用AsyncQueryHandler实例直接调用startxxx()方法。

在使用startQuery()方法时,各个参数的含义需要说明一下(因为我第一次用的时候就很迷惑。。。):

token:一个令牌,像是”虎符”的作用吧,同一个AsyncQueryHandler类对象中,startQuery()和onQueryComplete()方法的token应该是一致的。

cookie: 这个是在startQuery()中传入,想在onQueryComplete()中使用的对象。没有的话传递null即可。

uri: 这个是想要操作的数据库对应的uri

projection: 想要查询的列

selection: 限制条件

selectionArgs: 限制条件的具体值

orderBy: 排序条件

另外,在实际开发过程中,我们不仅可以将AsyncQueryHandler拿来直接用,还可以根据自己的需要,写一个类似的抽象类,从而让传递的参数更灵活,实现更多的代码需求。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180909G0UC3N00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券