AsyncQueryHandler的使用

来源:互联网 发布:数组长度可以为0吗 编辑:程序博客网 时间:2024/06/07 11:56

AsyncQueryHandler是Handler的子类,文档上说,如果处理ContentProvider相关的内容,不用需要自行定义一套东西, 而可以简单的使用async方式。我想指代的就应该是AsyncQueryHandler类。该类是一个典型的模板类,为ContentProvider 的增删改查提供了很好的接口,提供了一个解决架构,final了一些方法,置空了一些方法。通过派生,实例化一些方法(不是每个对 ContentProvider的处理多需要全部做增删改查,我想这也是该类默认置空一些方法而不是抽象一些方法的原因),来达到这个目的。在内部,该类 隐藏了多线程处理的细节,当你使用时,你会感觉异常便利。


1. 当你实例化一个AsyncQueryHandler类时(包括其子类...),它会单件构造一个线程(后面会详述...),这个线程里面会构建一个消息循环。
2. 获得该消息循环的指针,用它做参数实例化另一个Handler类,该类为内部类。至此,就有了两个线程,各自有一个Handler来处理消息。
3. 当调用onXXX的时候,在XXX函数内部会将请求封装成一个内部的参数类,将其作为消息的参数,将此消息发送至另一个线程。
4. 在该线程的Handler中,接受该消息,并分析传入的参数,用初始化时传入的ContentResolver进行XXX操作,并返回Cursor或其他返回值。
5. 构造一个消息,将上述返回值以及其他相关内容绑定在该消息上,发送回主线程。
6. 主线程默认的AsyncQueryHandler类的handleMessage方法(可自定义,但由于都是内部类,基本没有意义...)会分析该消息,并转发给对应的onXXXComplete方法。
7. 用户重写的onXXXComplete方法开始工作。


/*
* Copyright (C) 2012 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 com.example.testasyncqueryhandler;

import android.database.AbstractCursor;
import android.database.CursorIndexOutOfBoundsException;

/**
 * A cursor that is empty.
 * <p>
 * If you want an empty cursor, this class is better than a MatrixCursor because it has less
 * overhead.
 */
final public class EmptyCursor extends AbstractCursor {

    private String[] mColumns;

    public EmptyCursor(String[] columns) {
        this.mColumns = columns;
    }

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public String[] getColumnNames() {
        return mColumns;
    }

    @Override
    public String getString(int column) {
        throw cursorException();
    }

    @Override
    public short getShort(int column) {
        throw cursorException();
    }

    @Override
    public int getInt(int column) {
        throw cursorException();
    }

    @Override
    public long getLong(int column) {
        throw cursorException();
    }

    @Override
    public float getFloat(int column) {
        throw cursorException();
    }

    @Override
    public double getDouble(int column) {
        throw cursorException();
    }

    @Override
    public boolean isNull(int column) {
        throw cursorException();
    }

    private CursorIndexOutOfBoundsException cursorException() {
        return new CursorIndexOutOfBoundsException("Operation not permitted on an empty cursor.");
    }
}

/*
 * Copyright (C) 2011 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 com.example.testasyncqueryhandler;

import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabaseCorruptException;
import android.database.sqlite.SQLiteDiskIOException;
import android.database.sqlite.SQLiteFullException;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.CallLog.Calls;
import android.util.Log;

import java.lang.ref.WeakReference;

/** Handles asynchronous queries to the call log. */
public class CallLogQueryHandler extends NoNullCursorAsyncQueryHandler {

    private static final String TAG = "CallLogQueryHandler";

    private static final int QUERY_CALLLOG_TOKEN = 0;

    private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 2;

    private final WeakReference<Listener> mListener;

    private Cursor mCallLogCursor;

    protected class CatchingWorkerHandler extends
            AsyncQueryHandler.WorkerHandler {

        /**
         * catch the exception and print it
         *
         * @param looper
         */
        public CatchingWorkerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            try {
                // Perform same query while catching any exceptions
                super.handleMessage(msg);
            } catch (SQLiteDiskIOException e) {
                Log.w(TAG, "Exception on background worker thread", e);
            } catch (SQLiteFullException e) {
                Log.w(TAG, "Exception on background worker thread", e);
            } catch (SQLiteDatabaseCorruptException e) {
                Log.w(TAG, "Exception on background worker thread", e);
            }
        }
    }

    /**
     * call the insertTheData to insert the database
     *
     * @param token
     * @param cookie
     * @param uri
     * @param initialValues
     */
    public void insertTheData(int token, int cookie, Uri uri,
            ContentValues initialValues) {

        startInsert(token, cookie, uri, initialValues);
    }

    /**
     * delete the data from the database
     *
     * @param token
     * @param cookie
     * @param uri
     * @param selection
     * @param selectionArgs
     */
    public void deleteTheData(int token, Object cookie, Uri uri,
            String selection, String[] selectionArgs) {

        startDelete(token, cookie, uri, selection, selectionArgs);

    }

    /**
     * update the data from the database
     *
     * @param token
     * @param cookie
     * @param uri
     * @param values
     * @param selection
     * @param selectionArgs
     */
    public void updateData(int token, Object cookie, Uri uri,
            ContentValues values, String selection, String[] selectionArgs) {

        startUpdate(token, cookie, uri, values, selection, selectionArgs);

    }

    /**
     * query the data from the database;
     *
     * @param token
     * @param requestId
     * @param callType
     * @param showType
     * @param newOnly
     * @param newerThan
     * @param context
     */
    private void startQueryData(int token, int requestId, int callType,
            int showType, boolean newOnly, long newerThan, Context context) {

        startQuery(token, requestId, null, null, null, null,
                Calls.DEFAULT_SORT_ORDER);
    }

    @Override
    protected Handler createHandler(Looper looper) {
        // Provide our special handler that catches exceptions
        return new CatchingWorkerHandler(looper);
    }

    public CallLogQueryHandler(ContentResolver contentResolver,
            Listener listener) {
        this(contentResolver, listener, -1);
    }

    /**
     * construct the handler class
     * @param contentResolver
     * @param listener
     * @param limit
     */
    public CallLogQueryHandler(ContentResolver contentResolver,
            Listener listener, int limit) {
        super(contentResolver);
        mListener = new WeakReference<Listener>(listener);
    }

    @Override
    protected void onNotNullableQueryComplete(int token, Object cookie,
            Cursor cursor) {
        Log.d(TAG, "token==" + token + "cookie==" + cookie);
        if (token == QUERY_CALLLOG_TOKEN) {
        } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) {
            updateVoicemailStatus(cursor);
            return;
        } else {
            updateVoicemailStatus(cursor);
        }

        if (mCallLogCursor != null) {
            updateAdapterData(mCallLogCursor);
            mCallLogCursor = null;
        }
    }

    /**
     * Updates the adapter in the call log fragment to show the new cursor data.
     */
    private void updateAdapterData(Cursor combinedCursor) {
        final Listener listener = mListener.get();
        if (listener != null) {
            listener.onCallsFetched(combinedCursor);
        }
    }

    private void updateVoicemailStatus(Cursor statusCursor) {
        final Listener listener = mListener.get();
        if (listener != null) {
            listener.onVoicemailStatusFetched(statusCursor);
        }
    }

    /** Listener to completion of various queries. */
    public interface Listener {
        /**
         * Called when {@link CallLogQueryHandler#fetchVoicemailStatus()}
         * completes.
         */
        void onVoicemailStatusFetched(Cursor statusCursor);

        /**
         * Called when {@link CallLogQueryHandler#fetchCalls(int)}complete.
         */
        void onCallsFetched(Cursor combinedCursor);
    }
}

/*
 * Copyright (C) 2012 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 com.example.testasyncqueryhandler;

import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;

public abstract class NoNullCursorAsyncQueryHandler extends AsyncQueryHandler {

    public NoNullCursorAsyncQueryHandler(ContentResolver cr) {
        super(cr);
    }

    @Override
    public void startQuery(int token, Object cookie, Uri uri,
            String[] projection, String selection, String[] selectionArgs,
            String orderBy) {
        final CookieWithProjection projectionCookie = new CookieWithProjection(
                cookie, projection);
        super.startQuery(token, projectionCookie, uri, projection, selection,
                selectionArgs, orderBy);
    }

    @Override
    protected final void onQueryComplete(int token, Object cookie, Cursor cursor) {
        CookieWithProjection projectionCookie = (CookieWithProjection) cookie;

        super.onQueryComplete(token, projectionCookie.originalCookie, cursor);

        if (cursor == null) {
            cursor = new EmptyCursor(projectionCookie.projection);
        }
        onNotNullableQueryComplete(token, projectionCookie.originalCookie,
                cursor);
    }

    protected abstract void onNotNullableQueryComplete(int token,
            Object cookie, Cursor cursor);

    /**
     * Class to add projection to an existing cookie.
     */
    private static class CookieWithProjection {
        public final Object originalCookie;
        public final String[] projection;

        public CookieWithProjection(Object cookie, String[] projection) {
            this.originalCookie = cookie;
            this.projection = projection;
        }
    }
}






0 0
原创粉丝点击