diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-12-15 14:57:25 -0800 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-12-16 20:09:13 -0800 |
commit | c91893511dc1b9e634648406c9ae61b15476e65d (patch) | |
tree | 3ad578a43734d2ed63403a8b9076c2c5c6d07dbe /core/java/android/widget/CursorAdapter.java | |
parent | 60e41fa4456ce6bc37a33b1e4b81a56e9411199b (diff) | |
download | frameworks_base-c91893511dc1b9e634648406c9ae61b15476e65d.zip frameworks_base-c91893511dc1b9e634648406c9ae61b15476e65d.tar.gz frameworks_base-c91893511dc1b9e634648406c9ae61b15476e65d.tar.bz2 |
Fix issue #3272082: Contacts: when going back from edit view,
list UI is not ready yet
This involves some reworking of Loaders.
Loaders, in particular CursorLoader, are now expected to retain
their current data after being stopped. This allows applications
to keep that data across onStop() -> onStart(), so when the user
returns to the app it doesn't have to wait for the data to reload
and thus cause flicker.
This includes various API changes to better reflect the new
semantics, plus a new LoaderCallbacks method to tell the application
when it is actually time to stop their use of a loader's data.
Note this is somewhat half-done, to help checking in the extensive
application changes that are required without causing build breakage.
Change-Id: Ib4b3bf8185a6da46e7f06ca125521d65e2e380a1
Diffstat (limited to 'core/java/android/widget/CursorAdapter.java')
-rw-r--r-- | core/java/android/widget/CursorAdapter.java | 93 |
1 files changed, 70 insertions, 23 deletions
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java index 4cf8785..516162a 100644 --- a/core/java/android/widget/CursorAdapter.java +++ b/core/java/android/widget/CursorAdapter.java @@ -67,7 +67,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, * This field should be made private, so it is hidden from the SDK. * {@hide} */ - protected DataSetObserver mDataSetObserver = new MyDataSetObserver(); + protected DataSetObserver mDataSetObserver; /** * This field should be made private, so it is hidden from the SDK. * {@hide} @@ -81,54 +81,81 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, /** * If set the adapter will call requery() on the cursor whenever a content change - * notification is delivered. Implies {@link #FLAG_REGISTER_CONTENT_OBSERVER} + * notification is delivered. Implies {@link #FLAG_REGISTER_CONTENT_OBSERVER}. + * + * @deprecated This option is discouraged, as it results in Cursor queries + * being performed on the application's UI thread and thus can cause poor + * responsiveness or even Application Not Responding errors. As an alternative, + * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}. */ + @Deprecated public static final int FLAG_AUTO_REQUERY = 0x01; /** * If set the adapter will register a content observer on the cursor and will call - * {@link #onContentChanged()} when a notification comes in. + * {@link #onContentChanged()} when a notification comes in. Be careful when + * using this flag: you will need to unset the current Cursor from the adapter + * to avoid leaks due to its registered observers. This flag is not needed + * when using a CursorAdapter with a + * {@link android.content.CursorLoader}. */ public static final int FLAG_REGISTER_CONTENT_OBSERVER = 0x02; /** - * Constructor. The adapter will call requery() on the cursor whenever - * it changes so that the most recent data is always displayed. + * Constructor that always enables auto-requery. + * + * @deprecated This option is discouraged, as it results in Cursor queries + * being performed on the application's UI thread and thus can cause poor + * responsiveness or even Application Not Responding errors. As an alternative, + * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}. * * @param c The cursor from which to get the data. * @param context The context */ + @Deprecated public CursorAdapter(Context context, Cursor c) { init(context, c, FLAG_AUTO_REQUERY); } /** - * Constructor + * Constructor that allows control over auto-requery. It is recommended + * you not use this, but instead {@link #CursorAdapter(Context, Cursor, int)}. + * When using this constructor, {@link #FLAG_REGISTER_CONTENT_OBSERVER} + * will always be set. + * * @param c The cursor from which to get the data. * @param context The context * @param autoRequery If true the adapter will call requery() on the * cursor whenever it changes so the most recent - * data is always displayed. + * data is always displayed. Using true here is discouraged. */ public CursorAdapter(Context context, Cursor c, boolean autoRequery) { init(context, c, autoRequery ? FLAG_AUTO_REQUERY : FLAG_REGISTER_CONTENT_OBSERVER); } /** - * Constructor + * Recommended constructor. + * * @param c The cursor from which to get the data. * @param context The context - * @param flags flags used to determine the behavior of the adapter + * @param flags Flags used to determine the behavior of the adapter; may + * be any combination of {@link #FLAG_AUTO_REQUERY} and + * {@link #FLAG_REGISTER_CONTENT_OBSERVER}. */ public CursorAdapter(Context context, Cursor c, int flags) { init(context, c, flags); } + /** + * @deprecated Don't use this, use the normal constructor. This will + * be removed in the future. + */ + @Deprecated protected void init(Context context, Cursor c, boolean autoRequery) { init(context, c, autoRequery ? FLAG_AUTO_REQUERY : FLAG_REGISTER_CONTENT_OBSERVER); } - protected void init(Context context, Cursor c, int flags) { + void init(Context context, Cursor c, int flags) { if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) { flags |= FLAG_REGISTER_CONTENT_OBSERVER; mAutoRequery = true; @@ -142,13 +169,15 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1; if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) { mChangeObserver = new ChangeObserver(); + mDataSetObserver = new MyDataSetObserver(); } else { mChangeObserver = null; + mDataSetObserver = null; } if (cursorPresent) { if (mChangeObserver != null) c.registerContentObserver(mChangeObserver); - c.registerDataSetObserver(mDataSetObserver); + if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver); } } @@ -275,22 +304,39 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, * Change the underlying cursor to a new cursor. If there is an existing cursor it will be * closed. * - * @param cursor the new cursor to be used + * @param cursor The new cursor to be used */ public void changeCursor(Cursor cursor) { - if (cursor == mCursor) { - return; + Cursor old = swapCursor(cursor); + if (old != null) { + old.close(); + } + } + + /** + * Swap in a new Cursor, returning the old Cursor. Unlike + * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em> + * closed. + * + * @param newCursor The new cursor to be used. + * @return Returns the previously set Cursor, or null if there wasa not one. + * If the given new Cursor is the same instance is the previously set + * Cursor, null is also returned. + */ + public Cursor swapCursor(Cursor newCursor) { + if (newCursor == mCursor) { + return null; } - if (mCursor != null) { - if (mChangeObserver != null) mCursor.unregisterContentObserver(mChangeObserver); - mCursor.unregisterDataSetObserver(mDataSetObserver); - mCursor.close(); + Cursor oldCursor = mCursor; + if (oldCursor != null) { + if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver); + if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver); } - mCursor = cursor; - if (cursor != null) { - if (mChangeObserver != null) cursor.registerContentObserver(mChangeObserver); - cursor.registerDataSetObserver(mDataSetObserver); - mRowIDColumn = cursor.getColumnIndexOrThrow("_id"); + mCursor = newCursor; + if (newCursor != null) { + if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver); + if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver); + mRowIDColumn = newCursor.getColumnIndexOrThrow("_id"); mDataValid = true; // notify the observers about the new cursor notifyDataSetChanged(); @@ -300,6 +346,7 @@ public abstract class CursorAdapter extends BaseAdapter implements Filterable, // notify the observers about the lack of a data set notifyDataSetInvalidated(); } + return oldCursor; } /** |