1 /* 2 * Copyright (C) 2006 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 17 package android.database; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.ContentResolver; 22 import android.net.Uri; 23 import android.os.Bundle; 24 25 import java.io.Closeable; 26 import java.util.Arrays; 27 import java.util.List; 28 29 /** 30 * This interface provides random read-write access to the result set returned 31 * by a database query. 32 * <p> 33 * Cursor implementations are not required to be synchronized so code using a Cursor from multiple 34 * threads should perform its own synchronization when using the Cursor. 35 * </p><p> 36 * Implementations should subclass {@link AbstractCursor}. 37 * </p> 38 */ 39 public interface Cursor extends Closeable { 40 /* 41 * Values returned by {@link #getType(int)}. 42 * These should be consistent with the corresponding types defined in CursorWindow.h 43 */ 44 /** Value returned by {@link #getType(int)} if the specified column is null */ 45 static final int FIELD_TYPE_NULL = 0; 46 47 /** Value returned by {@link #getType(int)} if the specified column type is integer */ 48 static final int FIELD_TYPE_INTEGER = 1; 49 50 /** Value returned by {@link #getType(int)} if the specified column type is float */ 51 static final int FIELD_TYPE_FLOAT = 2; 52 53 /** Value returned by {@link #getType(int)} if the specified column type is string */ 54 static final int FIELD_TYPE_STRING = 3; 55 56 /** Value returned by {@link #getType(int)} if the specified column type is blob */ 57 static final int FIELD_TYPE_BLOB = 4; 58 59 /** 60 * Returns the numbers of rows in the cursor. 61 * 62 * @return the number of rows in the cursor. 63 */ getCount()64 int getCount(); 65 66 /** 67 * Returns the current position of the cursor in the row set. 68 * The value is zero-based. When the row set is first returned the cursor 69 * will be at positon -1, which is before the first row. After the 70 * last row is returned another call to next() will leave the cursor past 71 * the last entry, at a position of count(). 72 * 73 * @return the current cursor position. 74 */ getPosition()75 int getPosition(); 76 77 /** 78 * Move the cursor by a relative amount, forward or backward, from the 79 * current position. Positive offsets move forwards, negative offsets move 80 * backwards. If the final position is outside of the bounds of the result 81 * set then the resultant position will be pinned to -1 or count() depending 82 * on whether the value is off the front or end of the set, respectively. 83 * 84 * <p>This method will return true if the requested destination was 85 * reachable, otherwise, it returns false. For example, if the cursor is at 86 * currently on the second entry in the result set and move(-5) is called, 87 * the position will be pinned at -1, and false will be returned. 88 * 89 * @param offset the offset to be applied from the current position. 90 * @return whether the requested move fully succeeded. 91 */ move(int offset)92 boolean move(int offset); 93 94 /** 95 * Move the cursor to an absolute position. The valid 96 * range of values is -1 <= position <= count. 97 * 98 * <p>This method will return true if the request destination was reachable, 99 * otherwise, it returns false. 100 * 101 * @param position the zero-based position to move to. 102 * @return whether the requested move fully succeeded. 103 */ moveToPosition(int position)104 boolean moveToPosition(int position); 105 106 /** 107 * Move the cursor to the first row. 108 * 109 * <p>This method will return false if the cursor is empty. 110 * 111 * @return whether the move succeeded. 112 */ moveToFirst()113 boolean moveToFirst(); 114 115 /** 116 * Move the cursor to the last row. 117 * 118 * <p>This method will return false if the cursor is empty. 119 * 120 * @return whether the move succeeded. 121 */ moveToLast()122 boolean moveToLast(); 123 124 /** 125 * Move the cursor to the next row. 126 * 127 * <p>This method will return false if the cursor is already past the 128 * last entry in the result set. 129 * 130 * @return whether the move succeeded. 131 */ moveToNext()132 boolean moveToNext(); 133 134 /** 135 * Move the cursor to the previous row. 136 * 137 * <p>This method will return false if the cursor is already before the 138 * first entry in the result set. 139 * 140 * @return whether the move succeeded. 141 */ moveToPrevious()142 boolean moveToPrevious(); 143 144 /** 145 * Returns whether the cursor is pointing to the first row. 146 * 147 * @return whether the cursor is pointing at the first entry. 148 */ isFirst()149 boolean isFirst(); 150 151 /** 152 * Returns whether the cursor is pointing to the last row. 153 * 154 * @return whether the cursor is pointing at the last entry. 155 */ isLast()156 boolean isLast(); 157 158 /** 159 * Returns whether the cursor is pointing to the position before the first 160 * row. 161 * 162 * @return whether the cursor is before the first result. 163 */ isBeforeFirst()164 boolean isBeforeFirst(); 165 166 /** 167 * Returns whether the cursor is pointing to the position after the last 168 * row. 169 * 170 * @return whether the cursor is after the last result. 171 */ isAfterLast()172 boolean isAfterLast(); 173 174 /** 175 * Returns the zero-based index for the given column name, or -1 if the column doesn't exist. 176 * If you expect the column to exist use {@link #getColumnIndexOrThrow(String)} instead, which 177 * will make the error more clear. 178 * 179 * @param columnName the name of the target column. 180 * @return the zero-based column index for the given column name, or -1 if 181 * the column name does not exist. 182 * @see #getColumnIndexOrThrow(String) 183 */ getColumnIndex(String columnName)184 int getColumnIndex(String columnName); 185 186 /** 187 * Returns the zero-based index for the given column name, or throws 188 * {@link IllegalArgumentException} if the column doesn't exist. If you're not sure if 189 * a column will exist or not use {@link #getColumnIndex(String)} and check for -1, which 190 * is more efficient than catching the exceptions. 191 * 192 * @param columnName the name of the target column. 193 * @return the zero-based column index for the given column name 194 * @see #getColumnIndex(String) 195 * @throws IllegalArgumentException if the column does not exist 196 */ getColumnIndexOrThrow(String columnName)197 int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException; 198 199 /** 200 * Returns the column name at the given zero-based column index. 201 * 202 * @param columnIndex the zero-based index of the target column. 203 * @return the column name for the given column index. 204 */ getColumnName(int columnIndex)205 String getColumnName(int columnIndex); 206 207 /** 208 * Returns a string array holding the names of all of the columns in the 209 * result set in the order in which they were listed in the result. 210 * 211 * @return the names of the columns returned in this query. 212 */ getColumnNames()213 String[] getColumnNames(); 214 215 /** 216 * Return total number of columns 217 * @return number of columns 218 */ getColumnCount()219 int getColumnCount(); 220 221 /** 222 * Returns the value of the requested column as a byte array. 223 * 224 * <p>The result and whether this method throws an exception when the 225 * column value is null or the column type is not a blob type is 226 * implementation-defined. 227 * 228 * @param columnIndex the zero-based index of the target column. 229 * @return the value of that column as a byte array. 230 */ getBlob(int columnIndex)231 byte[] getBlob(int columnIndex); 232 233 /** 234 * Returns the value of the requested column as a String. 235 * 236 * <p>The result and whether this method throws an exception when the 237 * column value is null or the column type is not a string type is 238 * implementation-defined. 239 * 240 * @param columnIndex the zero-based index of the target column. 241 * @return the value of that column as a String. 242 */ getString(int columnIndex)243 String getString(int columnIndex); 244 245 /** 246 * Retrieves the requested column text and stores it in the buffer provided. 247 * If the buffer size is not sufficient, a new char buffer will be allocated 248 * and assigned to CharArrayBuffer.data 249 * @param columnIndex the zero-based index of the target column. 250 * if the target column is null, return buffer 251 * @param buffer the buffer to copy the text into. 252 */ copyStringToBuffer(int columnIndex, CharArrayBuffer buffer)253 void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer); 254 255 /** 256 * Returns the value of the requested column as a short. 257 * 258 * <p>The result and whether this method throws an exception when the 259 * column value is null, the column type is not an integral type, or the 260 * integer value is outside the range [<code>Short.MIN_VALUE</code>, 261 * <code>Short.MAX_VALUE</code>] is implementation-defined. 262 * 263 * @param columnIndex the zero-based index of the target column. 264 * @return the value of that column as a short. 265 */ getShort(int columnIndex)266 short getShort(int columnIndex); 267 268 /** 269 * Returns the value of the requested column as an int. 270 * 271 * <p>The result and whether this method throws an exception when the 272 * column value is null, the column type is not an integral type, or the 273 * integer value is outside the range [<code>Integer.MIN_VALUE</code>, 274 * <code>Integer.MAX_VALUE</code>] is implementation-defined. 275 * 276 * @param columnIndex the zero-based index of the target column. 277 * @return the value of that column as an int. 278 */ getInt(int columnIndex)279 int getInt(int columnIndex); 280 281 /** 282 * Returns the value of the requested column as a long. 283 * 284 * <p>The result and whether this method throws an exception when the 285 * column value is null, the column type is not an integral type, or the 286 * integer value is outside the range [<code>Long.MIN_VALUE</code>, 287 * <code>Long.MAX_VALUE</code>] is implementation-defined. 288 * 289 * @param columnIndex the zero-based index of the target column. 290 * @return the value of that column as a long. 291 */ getLong(int columnIndex)292 long getLong(int columnIndex); 293 294 /** 295 * Returns the value of the requested column as a float. 296 * 297 * <p>The result and whether this method throws an exception when the 298 * column value is null, the column type is not a floating-point type, or the 299 * floating-point value is not representable as a <code>float</code> value is 300 * implementation-defined. 301 * 302 * @param columnIndex the zero-based index of the target column. 303 * @return the value of that column as a float. 304 */ getFloat(int columnIndex)305 float getFloat(int columnIndex); 306 307 /** 308 * Returns the value of the requested column as a double. 309 * 310 * <p>The result and whether this method throws an exception when the 311 * column value is null, the column type is not a floating-point type, or the 312 * floating-point value is not representable as a <code>double</code> value is 313 * implementation-defined. 314 * 315 * @param columnIndex the zero-based index of the target column. 316 * @return the value of that column as a double. 317 */ getDouble(int columnIndex)318 double getDouble(int columnIndex); 319 320 /** 321 * Returns data type of the given column's value. 322 * The preferred type of the column is returned but the data may be converted to other types 323 * as documented in the get-type methods such as {@link #getInt(int)}, {@link #getFloat(int)} 324 * etc. 325 *<p> 326 * Returned column types are 327 * <ul> 328 * <li>{@link #FIELD_TYPE_NULL}</li> 329 * <li>{@link #FIELD_TYPE_INTEGER}</li> 330 * <li>{@link #FIELD_TYPE_FLOAT}</li> 331 * <li>{@link #FIELD_TYPE_STRING}</li> 332 * <li>{@link #FIELD_TYPE_BLOB}</li> 333 *</ul> 334 *</p> 335 * 336 * @param columnIndex the zero-based index of the target column. 337 * @return column value type 338 */ getType(int columnIndex)339 int getType(int columnIndex); 340 341 /** 342 * Returns <code>true</code> if the value in the indicated column is null. 343 * 344 * @param columnIndex the zero-based index of the target column. 345 * @return whether the column value is null. 346 */ isNull(int columnIndex)347 boolean isNull(int columnIndex); 348 349 /** 350 * Deactivates the Cursor, making all calls on it fail until {@link #requery} is called. 351 * Inactive Cursors use fewer resources than active Cursors. 352 * Calling {@link #requery} will make the cursor active again. 353 * @deprecated Since {@link #requery()} is deprecated, so too is this. 354 */ 355 @Deprecated deactivate()356 void deactivate(); 357 358 /** 359 * Performs the query that created the cursor again, refreshing its 360 * contents. This may be done at any time, including after a call to {@link 361 * #deactivate}. 362 * 363 * Since this method could execute a query on the database and potentially take 364 * a while, it could cause ANR if it is called on Main (UI) thread. 365 * A warning is printed if this method is being executed on Main thread. 366 * 367 * @return true if the requery succeeded, false if not, in which case the 368 * cursor becomes invalid. 369 * @deprecated Don't use this. Just request a new cursor, so you can do this 370 * asynchronously and update your list view once the new cursor comes back. 371 */ 372 @Deprecated requery()373 boolean requery(); 374 375 /** 376 * Closes the Cursor, releasing all of its resources and making it completely invalid. 377 * Unlike {@link #deactivate()} a call to {@link #requery()} will not make the Cursor valid 378 * again. 379 */ close()380 void close(); 381 382 /** 383 * return true if the cursor is closed 384 * @return true if the cursor is closed. 385 */ isClosed()386 boolean isClosed(); 387 388 /** 389 * Register an observer that is called when changes happen to the content backing this cursor. 390 * Typically the data set won't change until {@link #requery()} is called. 391 * 392 * @param observer the object that gets notified when the content backing the cursor changes. 393 * @see #unregisterContentObserver(ContentObserver) 394 */ registerContentObserver(ContentObserver observer)395 void registerContentObserver(ContentObserver observer); 396 397 /** 398 * Unregister an observer that has previously been registered with this 399 * cursor via {@link #registerContentObserver}. 400 * 401 * @param observer the object to unregister. 402 * @see #registerContentObserver(ContentObserver) 403 */ unregisterContentObserver(ContentObserver observer)404 void unregisterContentObserver(ContentObserver observer); 405 406 /** 407 * Register an observer that is called when changes happen to the contents 408 * of the this cursors data set, for example, when the data set is changed via 409 * {@link #requery()}, {@link #deactivate()}, or {@link #close()}. 410 * 411 * @param observer the object that gets notified when the cursors data set changes. 412 * @see #unregisterDataSetObserver(DataSetObserver) 413 */ registerDataSetObserver(DataSetObserver observer)414 void registerDataSetObserver(DataSetObserver observer); 415 416 /** 417 * Unregister an observer that has previously been registered with this 418 * cursor via {@link #registerContentObserver}. 419 * 420 * @param observer the object to unregister. 421 * @see #registerDataSetObserver(DataSetObserver) 422 */ unregisterDataSetObserver(DataSetObserver observer)423 void unregisterDataSetObserver(DataSetObserver observer); 424 425 /** 426 * Register to watch a content URI for changes. This can be the URI of a specific data row (for 427 * example, "content://my_provider_type/23"), or a a generic URI for a content type. 428 * 429 * <p>Calling this overrides any previous call to 430 * {@link #setNotificationUris(ContentResolver, List)}. 431 * 432 * @param cr The content resolver from the caller's context. The listener attached to 433 * this resolver will be notified. 434 * @param uri The content URI to watch. 435 */ setNotificationUri(ContentResolver cr, Uri uri)436 void setNotificationUri(ContentResolver cr, Uri uri); 437 438 /** 439 * Similar to {@link #setNotificationUri(ContentResolver, Uri)}, except this version allows 440 * to watch multiple content URIs for changes. 441 * 442 * <p>If this is not implemented, this is equivalent to calling 443 * {@link #setNotificationUri(ContentResolver, Uri)} with the first URI in {@code uris}. 444 * 445 * <p>Calling this overrides any previous call to 446 * {@link #setNotificationUri(ContentResolver, Uri)}. 447 * 448 * @param cr The content resolver from the caller's context. The listener attached to 449 * this resolver will be notified. 450 * @param uris The content URIs to watch. 451 */ setNotificationUris(@onNull ContentResolver cr, @NonNull List<Uri> uris)452 default void setNotificationUris(@NonNull ContentResolver cr, @NonNull List<Uri> uris) { 453 setNotificationUri(cr, uris.get(0)); 454 } 455 456 /** 457 * Return the URI at which notifications of changes in this Cursor's data 458 * will be delivered, as previously set by {@link #setNotificationUri}. 459 * @return Returns a URI that can be used with 460 * {@link ContentResolver#registerContentObserver(android.net.Uri, boolean, ContentObserver) 461 * ContentResolver.registerContentObserver} to find out about changes to this Cursor's 462 * data. May be null if no notification URI has been set. 463 */ getNotificationUri()464 Uri getNotificationUri(); 465 466 /** 467 * Return the URIs at which notifications of changes in this Cursor's data 468 * will be delivered, as previously set by {@link #setNotificationUris}. 469 * 470 * <p>If this is not implemented, this is equivalent to calling {@link #getNotificationUri()}. 471 * 472 * @return Returns URIs that can be used with 473 * {@link ContentResolver#registerContentObserver(android.net.Uri, boolean, ContentObserver) 474 * ContentResolver.registerContentObserver} to find out about changes to this Cursor's 475 * data. May be null if no notification URI has been set. 476 */ getNotificationUris()477 default @Nullable List<Uri> getNotificationUris() { 478 final Uri notifyUri = getNotificationUri(); 479 return notifyUri == null ? null : Arrays.asList(notifyUri); 480 } 481 482 /** 483 * onMove() will only be called across processes if this method returns true. 484 * @return whether all cursor movement should result in a call to onMove(). 485 */ getWantsAllOnMoveCalls()486 boolean getWantsAllOnMoveCalls(); 487 488 /** 489 * Sets a {@link Bundle} that will be returned by {@link #getExtras()}. 490 * 491 * @param extras {@link Bundle} to set, or null to set an empty bundle. 492 */ setExtras(Bundle extras)493 void setExtras(Bundle extras); 494 495 /** 496 * Returns a bundle of extra values. This is an optional way for cursors to provide out-of-band 497 * metadata to their users. One use of this is for reporting on the progress of network requests 498 * that are required to fetch data for the cursor. 499 * 500 * <p>These values may only change when requery is called. 501 * @return cursor-defined values, or {@link android.os.Bundle#EMPTY Bundle.EMPTY} if there 502 * are no values. Never <code>null</code>. 503 */ getExtras()504 Bundle getExtras(); 505 506 /** 507 * This is an out-of-band way for the the user of a cursor to communicate with the cursor. The 508 * structure of each bundle is entirely defined by the cursor. 509 * 510 * <p>One use of this is to tell a cursor that it should retry its network request after it 511 * reported an error. 512 * @param extras extra values, or {@link android.os.Bundle#EMPTY Bundle.EMPTY}. 513 * Never <code>null</code>. 514 * @return extra values, or {@link android.os.Bundle#EMPTY Bundle.EMPTY}. 515 * Never <code>null</code>. 516 */ respond(Bundle extras)517 Bundle respond(Bundle extras); 518 } 519