diff options
author | Alan Viverette <alanv@google.com> | 2014-10-23 00:04:03 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-10-23 00:04:09 +0000 |
commit | 183cef06df00c20df97b6a964dead91c1f7fa0a2 (patch) | |
tree | 2eb2e9c70afe9c3bcf479dfe0997c3a0a41b184c /core/java/android/widget | |
parent | 1eb6a2f075bfc0b65f0accf0f03661d7a5152593 (diff) | |
parent | ec8e720ae209d975ac34dc66e51f280d9a9482ef (diff) | |
download | frameworks_base-183cef06df00c20df97b6a964dead91c1f7fa0a2.zip frameworks_base-183cef06df00c20df97b6a964dead91c1f7fa0a2.tar.gz frameworks_base-183cef06df00c20df97b6a964dead91c1f7fa0a2.tar.bz2 |
Merge "Ensure AdapterView doesn't post selection notifications forever" into lmp-mr1-dev
Diffstat (limited to 'core/java/android/widget')
-rw-r--r-- | core/java/android/widget/AdapterView.java | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index b9f891c..5fa6e60 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -215,7 +215,12 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { private boolean mDesiredFocusableState; private boolean mDesiredFocusableInTouchModeState; + /** Lazily-constructed runnable for dispatching selection events. */ private SelectionNotifier mSelectionNotifier; + + /** Selection notifier that's waiting for the next layout pass. */ + private SelectionNotifier mPendingSelectionNotifier; + /** * When set to true, calls to requestLayout() will not propagate up the parent hierarchy. * This is used to layout the children during a layout pass. @@ -854,39 +859,50 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { private class SelectionNotifier implements Runnable { public void run() { + mPendingSelectionNotifier = null; + if (mDataChanged) { - // Data has changed between when this SelectionNotifier - // was posted and now. We need to wait until the AdapterView - // has been synched to the new data. + // Data has changed between when this SelectionNotifier was + // posted and now. Postpone the notification until the next + // layout is complete and we run checkSelectionChanged(). if (getAdapter() != null) { - post(this); + mPendingSelectionNotifier = this; } } else { - fireOnSelected(); - performAccessibilityActionsOnSelected(); + dispatchOnItemSelected(); } } } void selectionChanged() { + // We're about to post or run the selection notifier, so we don't need + // a pending notifier. + mPendingSelectionNotifier = null; + if (mOnItemSelectedListener != null || AccessibilityManager.getInstance(mContext).isEnabled()) { if (mInLayout || mBlockLayoutRequests) { // If we are in a layout traversal, defer notification // by posting. This ensures that the view tree is - // in a consistent state and is able to accomodate + // in a consistent state and is able to accommodate // new layout or invalidate requests. if (mSelectionNotifier == null) { mSelectionNotifier = new SelectionNotifier(); + } else { + removeCallbacks(mSelectionNotifier); } post(mSelectionNotifier); } else { - fireOnSelected(); - performAccessibilityActionsOnSelected(); + dispatchOnItemSelected(); } } } + private void dispatchOnItemSelected() { + fireOnSelected(); + performAccessibilityActionsOnSelected(); + } + private void fireOnSelected() { if (mOnItemSelectedListener == null) { return; @@ -1042,12 +1058,22 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { notifySubtreeAccessibilityStateChangedIfNeeded(); } + /** + * Called after layout to determine whether the selection position needs to + * be updated. Also used to fire any pending selection events. + */ void checkSelectionChanged() { if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) { selectionChanged(); mOldSelectedPosition = mSelectedPosition; mOldSelectedRowId = mSelectedRowId; } + + // If we have a pending selection notification -- and we won't if we + // just fired one in selectionChanged() -- run it now. + if (mPendingSelectionNotifier != null) { + mPendingSelectionNotifier.run(); + } } /** |