研究AsyncQueryHandler这个类的时候遇到了几个重要的不清楚的知识点
1. Handler与Thread,Looper的关系
2. HandlerThread是干什么用的
3. ThreadLocal类是干什么用的
Handler 主要是用来发送和处理消息,但是发送了消息后,消息是怎么传递的呢?这就是Looper的作用了,每个Handler中都会有一个Looper对象,如果在创建Handler的时候不指定,系统就会默认将当前线程的Looper绑定到Handler上,Looper对象中维护者一个消息队列,Hander 发送的消息都会存储到这个消息队列中,Looper不断的遍历这个消息队列,取出消息,交给handleMessage方法处理。Looper属于哪个线程,hadleMessage方法就会在那个线程中执行。HandlerThread不但能提供异步处理,Handler处理消息的方法也会在这个线程中执行,他最要的作用就是提供了一个线程。(这个类还有待研究)
ThreadLocal类主要是用来多个模块共享变量用的,但是不同线程之间的变量的值却不相同。AsyncQueryHandler的工作机制是什么?
AsyncQueryHandler 继承了Handler对象,但是他提供的构造方法中却没有Looper参数,也就是说他和他所在的当前线程绑定,AsyncQueryHandler内部有一个Hhandler对象,叫mWorkerHandler,他和一个HandlerThread绑定,mWorkerHandler负责将打包好的消息发送,并且处理,并将结果作为消息发送给AsyncQueryHandler。他是怎么发送的?AsyncQueryHandler内部有一个 WorkerArgs完美类,他封装了startAsyncQuery等方法的参数,并且通过这行代码
java代码:
WorkerArgs args = new WorkerArgs();
args.handler = this;
复制代码将当前Handler封装进去,发送到HandlerThread中去,mWorkerHandler处理完消息得到结果后,args.handler将结构发送给自己进行处理。(这就是线程间的通信了)
mWorkerHandler和一个子线程绑定,能够处理比较耗时的操作,AsyncQueryHandler提供异步处理。
1,若我们不用AsyncQueryHandler,直接在UI 线程调用ContentResolve去操作数据库比如查询,若你的数据库的数据很少还好,若很多,就会出现ANR了。一般解决ANR,就是开thread去解决。我在去年做案子的时候,就遇到这样的情况,数据太多了,我不得不开thread去查询,那开了Thread就得通过Handler来和UI线程交互,让UI线程知道何时查询完毕,可以更新UI将查询的结果表现出来。
2,若我们用AsyncQueryHandler,AsyncQueryHandler它就会主动地帮你开了Thread来避免ANR,并且它是继承于Handler,所以就可以通过onCompleteQuery来通知UI线程已经查询(删除...)完了。
短信操作的异步类,在执行查下短信时,可以先调用srartQuery方法执行异步查询,然后在调用onQueryComplete方法实现数据的更新。
mQueryHandler.startQuery(i, null, uri, null, null, null, null);
private final class QueryHandler extends AsyncQueryHandler{public QueryHandler(ContentResolver cr) {
super(cr);
// TODO Auto-generated constructor stub
}@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// TODO Auto-generated method stub
super.onQueryComplete(token, cookie, cursor);
if(cursor.getCount() > 0){
int count = cursor.getCount();
sizeMap.put(token, count);
mAdapter.notifyDataSetChanged();
}
cursor.close();
}
}
十一、Android学习笔记_AsyncQueryHandler的应用