【安卓筆記】AsyncQueryHandler源碼剖析,asyncqueryhandler

來源:互聯網
上載者:User

【安卓筆記】AsyncQueryHandler源碼剖析,asyncqueryhandler
AsyncQueryHandler類用於提供非同步資料庫操作(增刪改查)功能。本文視圖從源碼角度分析這個類。
1.AsyncQueryHandler使用方式:

AsyncQueryHandler handler = new AsyncQueryHandler(this.getContentResolver()){@Overrideprotected void onQueryComplete(int token, Object cookie,Cursor cursor){}@Overrideprotected void onUpdateComplete(int token, Object cookie, int result){}@Overrideprotected void onInsertComplete(int token, Object cookie, Uri uri){}@Overrideprotected void onDeleteComplete(int token, Object cookie, int result){}};handler.startQuery(token, cookie, uri, projection, selection, selectionArgs, orderBy);handler.startDelete(token, cookie, uri, selection, selectionArgs);handler.startInsert(token, cookie, uri, initialValues);handler.startUpdate(token, cookie, uri, values, selection, selectionArgs);

2.源碼分析

分析源碼前,從整體上把握這個類:每個AsyncQueryHandler對象都會開啟一個後台線程,線上程中執行與ContentProvider組件的資料互動,進行增刪改查。調用時,可以通過AsyncQueryHandler.startXXX系列方法將請求打包發送到後台線程,當相關處理完成後,會將結果非同步回傳給主線程並調用AsyncQueryHandler.onXXXComplete方法通知調用者。調用者每次請求時,需要傳入一個整型值token作為這次請求的標識,當該請求完成後進行回調時,會將token傳回,協助調用者確定這是哪一次請求。


AsyncQueryHandler是個抽象類別,不能直接被執行個體化,這點需要注意:

public abstract class AsyncQueryHandler extends Handler

其內部封裝了Looper和Handler,這個訊息迴圈工作在子線程。另提供4個常量標識當前操作類型。ContentResolver由構造器注入。
 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;    /* package */ final WeakReference<ContentResolver> mResolver;    private static Looper sLooper = null;    private Handler mWorkerThreadHandler;

背景工作執行緒的handler,即mWorkThreadHandler的handleMessage方法負責操作資料庫:
 protected class WorkerHandler extends Handler {        public WorkerHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(Message msg) {            final ContentResolver resolver = mResolver.get();            if (resolver == null) return;            WorkerArgs args = (WorkerArgs) msg.obj;            int token = msg.what;            int event = msg.arg1;            switch (event) {                case EVENT_ARG_QUERY:                    Cursor cursor;                    try {                        cursor = resolver.query(args.uri, args.projection,                                args.selection, args.selectionArgs,                                args.orderBy);                        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;                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;            }            //將結果返回給AsyncQueryHandler的handleMessage處理            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在構造的時候,會建立一個HandlerThread,start之,然後擷取其Looper,並利用其Looper構建子線程訊息迴圈,並與mWorkThreadHandler綁定:
  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);    }    protected Handler createHandler(Looper looper) {        return new WorkerHandler(looper);    }
這個類提供了WorkerArgs封裝資料庫操作的請求參數:
 protected static final class WorkerArgs {        public Uri uri;        public Handler handler;        public String[] projection;        public String selection;        public String[] selectionArgs;        public String orderBy;        public Object result;        public Object cookie;        public ContentValues values;    }

當外界調用startXXX方法時,其實會構造WorkerArgs對象,然後將這個對象以訊息的形式發送給mWorkThreadHandler  ,處理完成後將結果發送給AsyncQueryHandler本身:startXXX:
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();        args.handler = this;//注意這行制定了Handler為本身,即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);//交給子線程處理    }

WorkerHandler:
 Message reply = args.handler.obtainMessage(token);            reply.obj = args;            reply.arg1 = msg.arg1;   ...          reply.sendToTarget();//在startXXX方法中已經制定了target為AsyncQuertHandler本身
最終,操作結果交由AsyncQueryHandler類的handleMessage處理:
  @Override    public void handleMessage(Message msg) {        WorkerArgs args = (WorkerArgs) msg.obj;        if (localLOGV) {            Log.d(TAG, "AsyncQueryHandler.handleMessage: msg.what=" + msg.what                    + ", msg.arg1=" + msg.arg1);        }        int token = msg.what;        int event = msg.arg1;        // pass token back to caller on each callback.        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;        }    }
而AsyncQueryHandler類的handleMessage方法回調了onXXXcomplete系列方法。我們重寫onXXXcomplete方法即可拿到資料庫操作結果。

這個設計太贊了!!!!









聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.