AsyncQueryHandler分析

2017-09-13 20:36:01来源:CSDN作者:u012439416人点击

分享

作用: 对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之间发送消息进行线程间的切换,

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

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台