1cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/* 2cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project 3cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * 4cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * you may not use this file except in compliance with the License. 6cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * You may obtain a copy of the License at 7cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * 8cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * 10cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * See the License for the specific language governing permissions and 14cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * limitations under the License. 15cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */ 16cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 17cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpackage android.support.v4.content; 18cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 19cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.content.Context; 20cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.database.ContentObserver; 21cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.database.Cursor; 22cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.net.Uri; 23cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 24cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.FileDescriptor; 25cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.PrintWriter; 26cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.util.Arrays; 27cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 28cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/** 29cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Static library support version of the framework's {@link android.content.CursorLoader}. 30cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Used to write apps that run on platforms prior to Android 3.0. When running 31cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * on Android 3.0 or above, this implementation is still used; it does not try 32cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * to switch to the framework's implementation. See the framework SDK 33cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * documentation for a class overview. 34cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */ 35cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpublic class CursorLoader extends AsyncTaskLoader<Cursor> { 36cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn final ForceLoadContentObserver mObserver; 37cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 38cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn Uri mUri; 39cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn String[] mProjection; 40cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn String mSelection; 41cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn String[] mSelectionArgs; 42cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn String mSortOrder; 43cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 44cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn Cursor mCursor; 45cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 46cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn /* Runs on a worker thread */ 47cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 48cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public Cursor loadInBackground() { 49cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection, 50cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSelectionArgs, mSortOrder); 51cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (cursor != null) { 52cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn // Ensure the cursor window is filled 53cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn cursor.getCount(); 54de2eb627f0c4cb79c78e4d91ae7086d2c5e67eecScott Kennedy cursor.registerContentObserver(mObserver); 55cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 56cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return cursor; 57cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 58cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 59cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn /* Runs on the UI thread */ 60cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 61cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void deliverResult(Cursor cursor) { 62cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (isReset()) { 63cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn // An async query came in while the loader is stopped 64cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (cursor != null) { 65c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn cursor.close(); 66cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 67cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return; 68cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 69cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn Cursor oldCursor = mCursor; 70cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mCursor = cursor; 71cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 72cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (isStarted()) { 73cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn super.deliverResult(cursor); 74cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 75cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 76cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { 77c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn oldCursor.close(); 78cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 79cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 80cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 81cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn /** 82cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Creates an empty unspecified CursorLoader. You must follow this with 83cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc 84cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * to specify the query to perform. 85cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */ 86cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public CursorLoader(Context context) { 87cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn super(context); 88cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mObserver = new ForceLoadContentObserver(); 89cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 90cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 91cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn /** 92cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Creates a fully-specified CursorLoader. See 930574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * {@link android.content.ContentResolver#query(Uri, String[], String, String[], String) 94cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * ContentResolver.query()} for documentation on the meaning of the 95cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * parameters. These will be passed as-is to that call. 96cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */ 97cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public CursorLoader(Context context, Uri uri, String[] projection, String selection, 98cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn String[] selectionArgs, String sortOrder) { 99cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn super(context); 100cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mObserver = new ForceLoadContentObserver(); 101cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mUri = uri; 102cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mProjection = projection; 103cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSelection = selection; 104cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSelectionArgs = selectionArgs; 105cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSortOrder = sortOrder; 106cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 107cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 108cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn /** 109cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks 110cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * will be called on the UI thread. If a previous load has been completed and is still valid 111cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * the result may be passed to the callbacks immediately. 112cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * 113cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Must be called from the UI thread 114cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */ 115cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 116cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn protected void onStartLoading() { 117cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (mCursor != null) { 118cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn deliverResult(mCursor); 119cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 120cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (takeContentChanged() || mCursor == null) { 121cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn forceLoad(); 122cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 123cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 124cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 125cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn /** 126cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Must be called from the UI thread 127cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */ 128cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 129cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn protected void onStopLoading() { 130cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn // Attempt to cancel the current load task if possible. 131cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn cancelLoad(); 132cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 133cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 134cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 135cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void onCanceled(Cursor cursor) { 136cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (cursor != null && !cursor.isClosed()) { 137c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn cursor.close(); 138cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 139cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 140cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 141cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 142cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn protected void onReset() { 143cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn super.onReset(); 144cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 145cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn // Ensure the loader is stopped 146cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn onStopLoading(); 147cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 148cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn if (mCursor != null && !mCursor.isClosed()) { 149c286d5c93640e82c649888b7e5045801581e4d6cDianne Hackborn mCursor.close(); 150cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 151cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mCursor = null; 152cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 153cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 154cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public Uri getUri() { 155cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return mUri; 156cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 157cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 158cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void setUri(Uri uri) { 159cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mUri = uri; 160cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 161cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 162cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public String[] getProjection() { 163cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return mProjection; 164cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 165cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 166cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void setProjection(String[] projection) { 167cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mProjection = projection; 168cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 169cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 170cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public String getSelection() { 171cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return mSelection; 172cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 173cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 174cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void setSelection(String selection) { 175cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSelection = selection; 176cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 177cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 178cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public String[] getSelectionArgs() { 179cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return mSelectionArgs; 180cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 181cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 182cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void setSelectionArgs(String[] selectionArgs) { 183cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSelectionArgs = selectionArgs; 184cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 185cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 186cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public String getSortOrder() { 187cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn return mSortOrder; 188cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 189cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 190cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void setSortOrder(String sortOrder) { 191cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn mSortOrder = sortOrder; 192cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 193cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn 194cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn @Override 195cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 196cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn super.dump(prefix, fd, writer, args); 197cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mUri="); writer.println(mUri); 198cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mProjection="); 199cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.println(Arrays.toString(mProjection)); 200cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mSelection="); writer.println(mSelection); 201cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mSelectionArgs="); 202cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.println(Arrays.toString(mSelectionArgs)); 203cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder); 204cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mCursor="); writer.println(mCursor); 205cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged); 206cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn } 207cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn} 208