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