`
huangqinqin
  • 浏览: 360208 次
  • 性别: Icon_minigender_2
  • 来自: 福州
社区版块
存档分类
最新评论

Handler Looper的结合

 
阅读更多
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package android.content;

import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.lang.ref.WeakReference;

/**
* A helper class to help make handling asynchronous {@link ContentResolver}
* queries easier.
*/
public abstract class AsyncQueryHandler extends Handler {
    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;

    /* package */ final WeakReference<ContentResolver> mResolver;

    private static Looper sLooper = null;

    private Handler mWorkerThreadHandler;

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

    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);
                        // 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, e.toString());
                        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 to the 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 = 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);
    }

    /**
     * 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't going 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 the given URI.
     * @param selectionArgs You may include ?s in selection, which will be
     *         replaced by the values from 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 the ORDER BY itself). Passing null will use the
     *         default sort order, which may be unordered.
     */
    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;
        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 still may
     * 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 the same token they will all be canceled.
     */
    public final void cancelOperation(int token) {
        mWorkerThreadHandler.removeMessages(token);
    }

    /**
     * This method begins an asynchronous insert. When the insert operation is
     * 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 so cancelOperations works properly
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_INSERT;

        WorkerArgs args = new WorkerArgs();
        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 operation is
     * 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 so cancelOperations 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 operation is
     * 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 void startDelete(int token, Object cookie, Uri uri,
            String selection, String[] selectionArgs) {
        // Use the token as what so cancelOperations works properly
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_DELETE;

        WorkerArgs args = new WorkerArgs();
        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 void onQueryComplete(int token, 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 void onInsertComplete(int token, 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 void onUpdateComplete(int token, Object cookie, int result) {
        // 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 void onDeleteComplete(int token, Object cookie, int result) {
        // Empty
    }

    @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;
        }
    }
}
分享到:
评论

相关推荐

    Looper、Handler与HandlerThread

    Looper、Handler与HandlerThread相关概念与简介

    Android单线程模型中Message、Handler、Message Queue、Looper之间的关系---附实例源码

    消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理,在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件...

    Android-Event-driver.zip_Looper_android_android Handler_event

    在上一篇文章《Android应用程序消息处理机制(Looper、Handler)分析》中,我们分析了Android应用程序的消息处理机制,本文将结合这种消息处理机制来详细分析Android应用程序是如何获得键盘按键消息的。

    老罗android视频开发源码和ppt经典

    以下为视频源码目录: 一、Android入门介绍 视频教程 1.1 android系统介绍 1.2 android系统框架的介绍 1.3 如何搭建android开发环境 1.4 android生命周期的...15.6 Handler和Looper 15.7 Handler综合练习(图文混排)

    Android线程机制_2011_9_30更新

    根据开发经验以及android机制,结合Java多线程和android多线程,说明问题。 给初学android或者对android的多线程机制还有点迷惑的人做点贡献。该文档会持续更新。 推荐:...

    深入理解Android:卷I--详细书签版

     第5章讲解了Android源码中常用的类,如sp、wp、RefBase、Thread类、同步类、Java中的Handler类以及Looper类。这些类都是Android中最常用和最基本的,只有掌握这些类的知识,才 能在分析后续的代码时游刃有余。 ...

    android开发艺术探索高清完整版PDF

    / 375 10.2.2 消息队列的工作原理 / 380 10.2.3 Looper的工作原理 / 383 10.2.4 Handler的工作原理 / 385 10.3 主线程的消息循环 / 389 第11章 Android的线程和线程池 / 391 11.1 主线程和子线程 / 392 11.2 ...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    10.2.4 Handler的工作原理 385 10.3 主线程的消息循环 389 第11章 Android的线程和线程池 391 11.1 主线程和子线程 392 11.2 Android中的线程形态 392 11.2.1 AsyncTask 392 11.2.2 AsyncTask的工作原理 395 ...

    Android开发艺术探索

     10.2.4 Handler的工作原理 / 385  10.3 主线程的消息循环 / 389  第11章 Android的线程和线程池 / 391  11.1 主线程和子线程 / 392  11.2 Android中的线程形态 / 392  11.2.1 AsyncTask / 392  11.2.2 ...

    Android开发案例驱动教程 配套代码

    8.4.4 Looper和HandlerThread 172 本章小结 178 第9章 Activity和Intent 179 9.1 Activity 179 9.1.1 创建Activity 179 9.1.2 Activity生命周期 180 9.2 Intent 183 9.2.1 显式Intent 184 9.2.2 隐式Intent ...

Global site tag (gtag.js) - Google Analytics