summaryrefslogtreecommitdiffstats
path: root/core/java/android/content/AsyncQueryHandler.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
commit9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch)
treed88beb88001f2482911e3d28e43833b50e4b4e97 /core/java/android/content/AsyncQueryHandler.java
parentd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff)
downloadframeworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/content/AsyncQueryHandler.java')
-rw-r--r--core/java/android/content/AsyncQueryHandler.java360
1 files changed, 360 insertions, 0 deletions
diff --git a/core/java/android/content/AsyncQueryHandler.java b/core/java/android/content/AsyncQueryHandler.java
new file mode 100644
index 0000000..ac851cc
--- /dev/null
+++ b/core/java/android/content/AsyncQueryHandler.java
@@ -0,0 +1,360 @@
+/*
+ * 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) {
+ 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 that's 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;
+ }
+ }
+}