最近在做项目的时候,查看前辈写的代码,发现了AsyncQueryHandler.startQuery()这种写法。
由于以前一直没有使用过AsyncQueryHandler这个类,所以就根据网上查找到的信息和自己查看源码的的理解写下这篇文章。
本文的理解比较浅显,如果有理解错误,欢迎指正。
首先感谢如下两篇文章的作者,感谢他们的无私分享。
https://blog.csdn.net/weixin_42193691/article/details/82469627
https://blog.csdn.net/t12x3456/article/details/7912805
AsyncQueryHandler的简介
根据源码中的说明,可以很明显的发现AsyncQueryHandler是一个异步处理ContentProvider的抽象帮助类,该类可以实现ContentProvider的增删改查,但是根据类名和说明的话只能体现查这个功能,但是我为什么这样说呢,请看下面的WorkerHandler这个章节。
/**
* A helper class to help make handling asynchronous {@link ContentResolver}
* queries easier.
*/
public abstract class AsyncQueryHandler extends Handler {
我们一般在处理ContentProvider是直接通过ContentResolver直接处理的。在小数据的时候,这种方式是没有什么问题的。
但是当我们需要处理的数据是很大的时候,如果直接通过ContentResolver在UI线程中直接处理的话,很有可能会发生ANR异常(超过5秒)。
当然你也可以写个Handler去做这些操作,但是Android已经封装好异步查询框架AsyncQueryHandler,所以为什么不使用AsyncQueryHandler来让我们事半功倍呢。
AsyncQueryHandler实现原理
HandlerThread
查看AsyncQueryHandler的构造函数,发现首先构建一个HandlerThread,并且获取这个HandlerThread的Looper,然后通过Looper创建Handler。
所以AsyncQueryHandler构建一个可以用于异步操作的handler,并将前面创建的HandlerThread的Looper对象作为参数传递给当前的handler,这样当前的异步handler就拥有了HandlerThread的Looper对象,由于HandlerThread本身是异步线程,因此Looper也与异步线程绑定,从而handlerMessage方法也就可以异步处理耗时任务了,这样我们的Looper+Handler+MessageQueue+Thread异步循环机制构建完成。如果对于HandlerThread有什么不懂的,可以看看https://blog.csdn.net/javazejian/article/details/52426353这篇文章。
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.getLoop