AdapterView与Adapter(五) --AsyncQueryHandler
来源:互联网 发布:java 6 jre 32位下载 编辑:程序博客网 时间:2024/05/28 15:07
第一弹
今天晚上研究了一下啊AsyncQueryHandler,收获挺大,记录下重要知识点,以后继续补充研究。
研究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类主要是用来多个模块共享变量用的,但是不同线程之间的变量的值却不相同。
说明1:对象a,对象b比如说是某个类的实例对象,在模块A,B,C中共享对象a,还有对象b,在线程A中,模块A中设置a的值,在模块B,C中取出a的值,三个模块操作的是同一个值,但是对象a和对象b分别属于两个线程,他们是不同的。
AsyncQueryHandler的工作机制是什么?
AsyncQueryHandler继承了Handler对象,但是他提供的构造方法中却没有Looper参数,也就是说他和他所在的当前线程绑定,AsyncQueryHandler内部有一个Hhandler对象,叫mWorkerHandler,他和一个HandlerThread绑定,mWorkerHandler负责将打包好的消息发送,并且处理,并将结果作为消息发送给AsyncQueryHandler。他是怎么发送的?AsyncQueryHandler内部有一个WorkerArgs完美类,他封装了startAsyncQuery等方法的参数,并且通过这行代码
WorkerArgs args = new WorkerArgs();
args.handler = this;将当前Handler封装进去,发送到HandlerThread中去,mWorkerHandler处理完消息得到结果后,args.handler将结构发送给自己进行处理。(这就是线程间的通信了)
mWorkerHandler和一个子线程绑定,能够处理比较耗时的操作,AsyncQueryHandler提供异步处理。
总结:
Handler有两个作用,Handler用在一个线程中,就是实现异步操作。用在不同的线程之间,那就是异步操作加线程间通信。
补充:
HandlerThread:
先看他的类描述:Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
这是一个包含了Looper对象的线程,这个looper可以用来创建Handler对象,记住:start()方法必须被调用,否则通过getLooper方法得到的looper对象是空的。通过调用start方法,就会去执行该线程的run方法, public void run() {
mTid = Process.myTid();
Looper.prepare();//创建一个Looper实例,并且存储在ThreadLocal中,ThreadLocal中维护一个HashMap,键是线程号
synchronized (this) {
mLooper = Looper.myLooper();//得到当前线程的Looper,就是刚才perpare方法中创建并存储的那个Looper实例
Process.setThreadPriority(mPriority);
notifyAll();
}
onLooperPrepared();
Looper.loop();//开始轮询
mTid = -1;
}
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
AsyncQueryHandler是如何提供onxxxComplete方法给用户,由用户自己实现的?
public abstract class AsyncQueryHandler extends Handler 他是一个抽象类
MessageQueue是不是一个任务队列?
是,他是一个优先级队列(可以通过ArrayList的排序来实现)。它内部自己维护一个ArrayLsit集合,用来存储Message消息,Message消息有三种,普通消息,按照先发送先执行的FIFO原则进行;高优先级的消息,这种消息会直接插在队列的最前面,立刻执行;还有一种定时消息,类似于定时任务,到时间才执行。
Looper是如何轮询MessageQueue的?
当在主线程中使用Handler的时候,不用指定Looper,因为在主线程开启的时候,就已经调用了Looper.loop()方法开始轮询了。
挡在子线程中使用Handler的时候,通过调用Looper的prepare方法创建存储Looper对象,还得调用Looper.loop()方法开启轮询。
当配合HandlerThread使用Handler的时候,HandlerThread的run方法中调用了Looper.loop()方法。
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
}
Message消息实现了Parcelable接口
第二弹
官方文档对AsyncQueryHandler的解释非常简洁
A helper class to help make handling asynchronousContentResolver queries easier
下面解释一番,其实明白之后就会发现,真的就是一句话的事情而已.
AsyncQueryHandler:异步的查询操作帮助类,其实它同样可以处理增删改,
查询其API便可知,它担供:
startInsert()
startDelete()
startUpdate()
startQuery()
这四个操作,并提供相对应的onXXXComplete方法,以供操作完数据库后进行其它的操作,这四个onXXXComplete方法都是空实现,以便我们只需要去实现我们关注的操作。
如题所说,让ContentResolver的查询操作更简单,
首先,若我们不用AsyncQueryHandler,那么,在UI 线程调用ContentResolve去操作数据库,比如查询,若你的数据库的数据很少还好,若很多,就会出现ANR了。一般解决ANR,就是开thread去解决。然后呢,既然开了新的Thread,就得通过Handler来和UI线程交互,也就是查询完之后通过Handler发一个message通知主线程去更新UI.这一系列的操作其实还是挺繁琐的.
所以,A helper class to help make handling asynchronousContentResolver queries easier
那么,若我们用AsyncQueryHandler怎样做呢,AsyncQueryHandler它就会主动地帮你开了Thread来避免ANR,并且它是继承于Handler,所以就可以通过onCompleteQuery来通知UI线程已经查询(删除,更新,增加)完成。
所以,这两种实现方式的区别在于,工作是你自己写代码来做,还是调用现成的.
使用时直接调用startXXX方法即可。传入的通用参数如下:
token,一个令牌,主要用来标识查询,保证唯一即可.需要跟onXXXComplete方法传入的一致。(当然你也可以不一致,同样在数据库的操作结束后会调用对应的onXXXComplete方法 )
cookie,你想传给onXXXComplete方法使用的一个对象。(没有的话传递null即可)
Uri uri(进行查询的通用资源标志符):
projection 查询的列
selection 限制条件
selectionArgs 查询参数
orderBy 排序条件
private void startQuery() { Uri uri = Sms.CONVESATION_URI; mQueryHandler.startQuery(0, null, uri, CONVERSATION_PROJECTION, null, null, "sms.date desc"); } // 写一个异步查询类 private final class QueryHandler extends AsyncQueryHandler { public QueryHandler(ContentResolver cr) { super(cr); } @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); // 更新mAdapter的Cursor mAdapter.changeCursor(cursor); } }
第三弹
AsyncQueryHandler封装了调用者线程与工作线程的交互过程。交互的主体是两个Handler,一个运行在调用者线程中,一个运行在工作者线程中。通过提供onXXXComplete的回调接口,实现事件的完成处理。
public abstract class AsyncQueryHandler extends Handler {
protected class WorkerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// 运行在工作者线程中
WorkerArgs args = (WorkerArgs) msg.obj;
// 向调用者传回信息
Message reply = args.handler.obtainMessage(token);
}
}
public AsyncQueryHandler(ContentResolver cr) {
synchronized (AsyncQueryHandler.class) {
// 启动工作者线程
if (sLooper == null) {
HandlerThread thread = new HandlerThread("AsyncQueryWorker");
thread.start();
sLooper = thread.getLooper();
}
}
// 与工作者线程绑定的Hanlder
mWorkerThreadHandler = createHandler(sLooper);
}
public void startQuery(...) {
Message msg = mWorkerThreadHandler.obtainMessage(token);
WorkerArgs args = new WorkerArgs();
// 保存调用者Handler对象,以便回调
args.handler = this;
msg.obj = args;
// 向工作者线程发出处理请求
mWorkerThreadHandler.sendMessage(msg);
}
// 被子类重写的事件完成回调接口
protected void onDeleteComplete(int token, Object cookie, int result) {
}
@Override
public void handleMessage(Message msg) {
// 运行在调用者线程
switch (event) {
case EVENT_ARG_QUERY:
onQueryComplete(token, args.cookie, (Cursor) args.result);
break;
}
}
}
流程:startQuery->WorkerHandler::handleMessage->AsyncQueryHandler::handleMessage->onDeleteComplete
- AdapterView与Adapter(五) --AsyncQueryHandler
- AdapterView与Adapter(一)
- AdapterView与Adapter(二) --CursorAdapter
- AdapterView 与 Adapter
- Android高级控件----AdapterView与Adapter详解(转)
- AdapterView(五)
- 安卓Adapter 与AdapterView笔记
- Android高级控件----AdapterView与Adapter
- Android高级控件----AdapterView与Adapter
- Android高级控件----AdapterView与Adapter详解
- Android高级控件----AdapterView与Adapter
- Android高级控件----AdapterView与Adapter
- Android高级控件----AdapterView与Adapter
- Android学习笔记(22):AdapterView与Adapter
- Android高级控件----AdapterView与Adapter
- Android高级控件----AdapterView与Adapter
- Android高级控件----AdapterView与Adapter
- Android适配器视图与适配器AdapterView & Adapter
- 一个简单的自定义web框架
- Oracle通过时间点快照来恢复数据
- Android开发:带progressBar效果的Button
- 打开和保存文件的对话框
- unity3d 4.X音频格式
- AdapterView与Adapter(五) --AsyncQueryHandler
- POJ 3983 快算24(水~)
- Linux文件vi操作
- IT行业的职称
- linux批量重命名之xargs
- 字符串重组
- NTFS For Mac完全读写小能手
- php中同时包含OR运算与AND运算
- Connection is read-only. Queries leading to data modification are not allowed