AsyncQueryHandler

原文地址:http://blog.csdn.net/wcs542882916

packageandroid.content;

 

importandroid.database.Cursor;

importandroid.net.Uri;

importandroid.os.Handler;

importandroid.os.HandlerThread;

importandroid.os.Looper;

importandroid.os.Message;

importandroid.util.Log;

 

importjava.lang.ref.WeakReference;

 

/**

 * 这个异步查询Handler的原理就是两个Handler相互发消息。

 * 外部Handler#startQuery(发送消息到内部Handler),

 * 内部Handler(另外一个线程)接收消息并查询数据库,

 * 查询结束后,再从内部发消息到外部Handler通知查询完毕,

 * 外部Handler处理消息调用Handler#onQueryComplete,至此一个回合结束。

 *

 * Ahelper class to help make handling asynchronous {@link ContentResolver}

 *queries easier.

 *

 * 这是一个帮助类,使得ContentResolver异步查询更加便捷

 */

public abstract classAsyncQueryHandler extendsHandler {

    private static final String TAG = "AsyncQuery";

    private static final boolean localLOGV = false;

 

    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;

 

    /*

    *下面这三个成员变量都会在AsyncQueryHandler的构造方法里被初始化

    *

    *sLooper是另起了一个线程newHandlerThread("AsyncQueryWorker"),并获取此线程的Looper

    *

    *mWorkerThreadHandler使用sLooper创建的一个Handler,

    *这个Handler处理的message都会在Looper所在线程里执行

   */

    /* package */finalWeakReference<ContentResolver> mResolver;//弱引用,暂时不懂

    private staticLooper sLooper= null;

    private Handler mWorkerThreadHandler;

   

    protected static final classWorkerArgs {

       publicUri uri;

       publicHandler handler;

       publicString[] projection;

       publicString selection;

       publicString[] selectionArgs;

       publicString orderBy;

       publicObject result;

       publicObject cookie;

       publicContentValues values;

    }

 

    protected classWorkerHandler extendsHandler {

       publicWorkerHandler(Looper looper) {

           super(looper);

       }

 

       @Override

       public void handleMessage(Message msg) {

           finalContentResolver resolver = mResolver.get();

           if(resolver == null)return;

 

           WorkerArgs args = (WorkerArgs) msg.obj;

 

           inttoken = msg.what;

           intevent = msg.arg1;

 

           switch(event) {

                case EVENT_ARG_QUERY:

                    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.

                        //调用getCount()方法能够引起cursor window被填充,这将使得在主线程第一次存取的更快

                        if (cursor != null) {

                            cursor.getCount();

                        }

                    } catch (Exception e) {

                        Log.w(TAG, "Exceptionthrown during handling EVENT_ARG_QUERY",e);

                        cursor = null;

                    }

 

                    args.result = cursor;

                    break;

 

                case EVENT_ARG_INSERT:

                    args.result = resolver.insert(args.uri, args.values);

                    break;

 

                case EVENT_ARG_UPDATE:

                    args.result = resolver.update(args.uri, args.values, args.selection,

                            args.selectionArgs);

                    break;

 

                case EVENT_ARG_DELETE:

                    args.result = resolver.delete(args.uri, args.selection, args.selectionArgs);

                    break;

           }

 

           // passing the original token value back tothe caller

           // on top of the event values in arg1.

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

       }

    }

 

    public AsyncQueryHandler(ContentResolver cr) {

       super();

       mResolver= newWeakReference<ContentResolver>(cr);

       synchronized(AsyncQueryHandler.class){

           if(sLooper == null) {

                HandlerThread thread = new HandlerThread("AsyncQueryWorker");

                thread.start();

 

                sLooper = thread.getLooper();

           }

       }

       mWorkerThreadHandler= createHandler(sLooper);

    }

 

    protected Handler createHandler(Looper looper) {

       return new WorkerHandler(looper);

    }

 

    /**

    * This method begins an asynchronous query. When the query is done

    * {@link #onQueryComplete} is called.

    *

    * @param token A token passed into {@link#onQueryComplete} to identify

    *  the query.

    * @param cookie An object that gets passed into {@link #onQueryComplete}

    * @param uri The URI, using the content:// scheme, for the content to

    *         retrieve.

    * @param projection A list of which columns to return. Passing null will

    *         return all columns,which is discouraged to prevent reading data

    *         from storage that isn'tgoing to be used.

    * @param selection A filter declaring which rows to return, formatted as an

    *         SQL WHERE clause(excluding the WHERE itself). Passing null will

    *         return all rows for thegiven URI.

    * @param selectionArgs You may include ?s in selection, which will be

    *         replaced by the valuesfrom selectionArgs, in the order that they

    *         appear in the selection.The values will be bound as Strings.

    * @param orderBy How to order the rows, formatted as an SQL ORDER BY

    *         clause (excluding theORDER BY itself). Passing null will use the

    *         default sort order,which may be unordered.

    *        

    * 这个方法开始一个异步查询。当查询完成的时候#onQueryComplete方法会被调用。

    * token 一个token被传入到#onQueryComplete来标识查询的发起地。

    * cookie 一个对象被传入到#onQueryComplete方法内,可以是用来封装数据的对象。

    * projection 获取那些列数据,传入null值将查询所有列。

    * selection 获取那些行,传入null将查询所有行。

    * selectionArgs 在selection参数里可以加入一些?s,查询的时候这些?s将会被selectionArgs里的值替换。

    * orderBy 对行进行排序,传入null将会使用默认排序,默认排序也有可能是无序的。

    */

    public voidstartQuery(inttoken, Object cookie, Uri uri,

           String[] projection, String selection, String[] selectionArgs,

           String orderBy) {

       // Use the token as what socancelOperations works properly

       //将token作为Message#what字段,所以取消操作能够起作用。

       Message msg = mWorkerThreadHandler.obtainMessage(token);

       msg.arg1= EVENT_ARG_QUERY;

 

       WorkerArgs args = newWorkerArgs();

       args.handler= this;//AsyncQueryHandler

       args.uri= uri;

       args.projection= projection;

       args.selection= selection;

       args.selectionArgs= selectionArgs;

       args.orderBy= orderBy;

       args.cookie= cookie;

       

       msg.obj= args;

 

       mWorkerThreadHandler.sendMessage(msg);

    }

 

    /**

    * Attempts to cancel operation that has not already started. Note that

    * there is no guarantee that the operation will be canceled. They stillmay

    * result in a call to on[Query/Insert/Update/Delete]Complete after this

    * call has completed.

    *

    * @param token The token representing the operation to be canceled.

    *  If multiple operations have thesame token they will all be canceled.

    * 

    *  取消token所标识的Message。这里不保证取消操作会成功。

    */

    public final void cancelOperation(int token) {

       mWorkerThreadHandler.removeMessages(token);

    }

 

    /**

    * This method begins an asynchronous insert. When the insert operationis

    * done {@link #onInsertComplete} is called.

    *

    * @param token A token passed into {@link#onInsertComplete} to identify

    *  the insert operation.

    * @param cookie An object that gets passed into {@link #onInsertComplete}

    * @param uri the Uri passed to the insert operation.

    * @param initialValues the ContentValues parameter passed to the insert operation.

    *

    * 同上

    */

    public final void startInsert(int token, Object cookie, Uri uri,

           ContentValues initialValues) {

       // Use the token as what socancelOperations works properly

       Message msg = mWorkerThreadHandler.obtainMessage(token);

       msg.arg1= EVENT_ARG_INSERT;

 

       WorkerArgs args = newWorkerArgs();

       args.handler= this;

       args.uri= uri;

       args.cookie= cookie;

       args.values= initialValues;

       msg.obj= args;

 

       mWorkerThreadHandler.sendMessage(msg);

    }

 

    /**

    * This method begins an asynchronous update. When the update operationis

    * done {@link #onUpdateComplete} is called.

    *

    * @param token A token passed into {@link#onUpdateComplete} to identify

    *  the update operation.

    * @param cookie An object that gets passed into {@link #onUpdateComplete}

    * @param uri the Uri passed to the update operation.

    * @param values the ContentValues parameter passed to the update operation.

    */

    public final void startUpdate(int token, Object cookie, Uri uri,

           ContentValues values, String selection, String[] selectionArgs) {

       // Use the token as what socancelOperations works properly

       Message msg = mWorkerThreadHandler.obtainMessage(token);

       msg.arg1= EVENT_ARG_UPDATE;

 

        WorkerArgs args = new WorkerArgs();

       args.handler= this;

       args.uri= uri;

       args.cookie= cookie;

       args.values= values;

       args.selection= selection;

       args.selectionArgs= selectionArgs;

       msg.obj= args;

 

       mWorkerThreadHandler.sendMessage(msg);

    }

 

    /**

    * This method begins an asynchronous delete. When the delete operationis

    * done {@link #onDeleteComplete} is called.

    *

    * @param token A token passed into {@link#onDeleteComplete} to identify

    *  the delete operation.

    * @param cookie An object that gets passed into {@link #onDeleteComplete}

    * @param uri the Uri passed to the delete operation.

    * @param selection the where clause.

    */

    public final voidstartDelete(inttoken, Object cookie, Uri uri,

           String selection, String[] selectionArgs) {

       // Use the token as what socancelOperations works properly

       Message msg = mWorkerThreadHandler.obtainMessage(token);

       msg.arg1= EVENT_ARG_DELETE;

 

       WorkerArgs args = newWorkerArgs();

       args.handler= this;

       args.uri= uri;

       args.cookie= cookie;

       args.selection= selection;

       args.selectionArgs= selectionArgs;

       msg.obj= args;

 

       mWorkerThreadHandler.sendMessage(msg);

    }

 

    /**

    * Called when an asynchronous query is completed.

    *

    * @param token the token to identify the query, passed in from

    *            {@link #startQuery}.

    * @param cookie the cookie object passed in from {@link #startQuery}.

    * @param cursor The cursor holding the results from the query.

    */

    protected voidonQueryComplete(inttoken, Object cookie, Cursor cursor) {

       // Empty

    }

 

    /**

    * Called when an asynchronous insert is completed.

    *

    * @param token the token to identify the query, passed in from

    *        {@link #startInsert}.

    * @param cookie the cookie object that's passed in from

    *        {@link #startInsert}.

    * @param uri the uri returned from the insert operation.

    */

    protected voidonInsertComplete(inttoken, Object cookie, Uri uri) {

       // Empty

    }

 

    /**

    * Called when an asynchronous update is completed.

    *

    * @param token the token to identify the query, passed in from

    *        {@link #startUpdate}.

    * @param cookie the cookie object that's passed in from

    *        {@link #startUpdate}.

    * @param result the result returned from the update operation

    */

    protected voidonUpdateComplete(inttoken, Object cookie, intresult) {

       // Empty

    }

 

    /**

    * Called when an asynchronous delete is completed.

    *

    * @param token the token to identify the query, passed in from

    *        {@link #startDelete}.

    * @param cookie the cookie object that's passed in from

    *        {@link #startDelete}.

    * @param result the result returned from the delete operation

     */

    protected voidonDeleteComplete(inttoken, Object cookie, intresult) {

       // Empty

    }

 

    @Override

    public voidhandleMessage(Message msg) {

       WorkerArgs args = (WorkerArgs) msg.obj;

 

       if(localLOGV) {

           Log.d(TAG,"AsyncQueryHandler.handleMessage: msg.what="+ msg.what

                    + ", msg.arg1=" + msg.arg1);

       }

 

       inttoken = msg.what;

       intevent = msg.arg1;

 

       // pass token back to caller on eachcallback.

       switch(event) {

           case EVENT_ARG_QUERY:

                onQueryComplete(token, args.cookie, (Cursor) args.result);

                break;

 

           case EVENT_ARG_INSERT:

                onInsertComplete(token, args.cookie, (Uri) args.result);

                break;

 

           case EVENT_ARG_UPDATE:

                onUpdateComplete(token, args.cookie, (Integer) args.result);

                break;

 

           case EVENT_ARG_DELETE:

                onDeleteComplete(token, args.cookie, (Integer) args.result);

                break;

       }

    }

}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值