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