summaryrefslogtreecommitdiffstats
path: root/core/java/android/widget
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2014-10-23 00:04:03 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-10-23 00:04:09 +0000
commit183cef06df00c20df97b6a964dead91c1f7fa0a2 (patch)
tree2eb2e9c70afe9c3bcf479dfe0997c3a0a41b184c /core/java/android/widget
parent1eb6a2f075bfc0b65f0accf0f03661d7a5152593 (diff)
parentec8e720ae209d975ac34dc66e51f280d9a9482ef (diff)
downloadframeworks_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.java44
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();
+ }
}
/**