首页 » Android » AsyncQueryHandler分析

AsyncQueryHandler分析

原文 http://blog.csdn.net/u012439416/article/details/77969698

2017-09-13 21:20:07阅读(444)

作用: 对DB数据库进行异步操作,加快其数据处理的速度. 例如几千联系人的数据读取,按正常的处理速度会非常的慢,

使用AsyncQueryHandler,这就会大大的加快速度,增加用户的良好体验。

为什么会有AsyncQueryHandler?

1,若不用AsyncQueryHandler,直接在UI 线程调用ContentResolve去操作数据库,比如查询.如果数据库的数据很少,

无需担心ANR问题;如果有大量的数据,就会出现ANR。一般解决方法就是构造thread去查询,然后通过Handler来和

UI线程交互,让UI线程知道何时查询完毕,并且可以更新UI将查询的结果表现出来。

2,如果用AsyncQueryHandler,AsyncQueryHandler它就会主动地构造Thread来避免ANR,并且它是继承于Handler,

所以就可以通过回调方法来通知UI线程已经操作完成。

所以AsyncQueryHandler会做以下2件事情,

1,构造thread,

2,在thread中操作完成数据库之后切换到主线程并通过回调方法来进行交互。

AsyncQueryHandler是一个抽象类,定义如下,

public abstract class AsyncQueryHandler extends Handler {

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);
}

createHandler方法如下,

protected Handler createHandler(Looper looper) {
   return new WorkerHandler(looper);
}

WorkerHandler是AsyncQueryHandler的一个内部类,继承于Handler,

protected class WorkerHandler extends Handler {

由此可知, AsyncQueryHandler 首先利用HandlerThread开启了一个线程,并且利用该线程的Looper构造WorkerHandler对象,

这样当AsyncQueryHandler (UI线程) 给mWorkerThreadHandler发送消息时,就可以切换到子线程中执行,执行完成之后

mWorkerThreadHandler就会给AsyncQueryHandler发送消息,切换到主线程中执行。

AsyncQueryHandler有5个public方法,分别对应数据库的增删改查(startInsert/startDelete/ startUpdate/startQuery)方法,

还有一个停止的方法(cancelOperation),增删改查4个方法的逻辑完全相同,以startQuery方法为例论述原理。

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();//构造WorkerArgs对象
        args.handler = this;// AsyncQueryHandler对象
        args.uri = uri;// 数据库的URI对象
        args.projection = projection;
        args.selection = selection;
        args.selectionArgs = selectionArgs;
        args.orderBy = orderBy;
        args.cookie = cookie;
        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

主要是利用内部类WorkerArgs封装消息.4个方法对应不同的消息,

private static final int EVENT_ARG_QUERY = 1;
private static final int EVENT_ARG_INSERT = 2;
private static final int EVENT_ARG_UPDATE = 3;
private static final int EVENT_ARG_DELETE = 4;

WorkerHandler中的handleMessage主要处理逻辑如下,

1,从WorkerArgs中取出封装的消息,

final ContentResolver resolver = mResolver.get();//ContentResolver对象
if (resolver == null) return;
WorkerArgs args = (WorkerArgs) msg.obj;
int token = msg.what;
int event = msg.arg1;

2,根据不同的消息分别处理,调用数据库进行增删改查操作,对查询消息的处理如下,

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;

3,操作完成之后,给AsyncQueryHandler发送消息,

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();

AsyncQueryHandler的handleMessage方法主要是根据不同的消息分别调用不同的回调方法,

1,查询数据库完成之后调用onQueryComplete方法,

case EVENT_ARG_QUERY:
   onQueryComplete(token, args.cookie, (Cursor) args.result);
   break;

2,增加数据库完成之后调用onInsertComplete方法,

case EVENT_ARG_INSERT:
    onInsertComplete(token, args.cookie, (Uri) args.result);
    break;

3,更新数据库完成之后调用onUpdateComplete方法,

case EVENT_ARG_UPDATE:
    onUpdateComplete(token, args.cookie, (Integer) args.result);
    break;

4,删除数据库完成之后调用onDeleteComplete方法,

case EVENT_ARG_DELETE:
    onDeleteComplete(token, args.cookie, (Integer) args.result);
    break;

当然,这4个方法并不是抽象方法,而是protected方法.因此,子类并不需要实现所有4个方法,只需要根据需要实现即可。

AsyncQueryHandler主要就是利用内部类WorkerHandler和AsyncQueryHandler之间发送消息进行线程间的切换,

增删改查耗时操作都是在子线程中执行,并且执行完成之后利用回调进行交互。

最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹