diff options
author | Gilles Debunne <debunne@google.com> | 2011-01-17 15:14:32 -0800 |
---|---|---|
committer | Gilles Debunne <debunne@google.com> | 2011-01-19 15:10:09 -0800 |
commit | be2c4f92a990ca48ad6ede252343dd9574dfe505 (patch) | |
tree | 4b800d707c3e0f802a7b0ffc29bcabd8fb1f1089 /core/java/android/widget/ArrayAdapter.java | |
parent | 9240f16d771549b62b5f10efe9f784d87a0afaa4 (diff) | |
download | frameworks_base-be2c4f92a990ca48ad6ede252343dd9574dfe505.zip frameworks_base-be2c4f92a990ca48ad6ede252343dd9574dfe505.tar.gz frameworks_base-be2c4f92a990ca48ad6ede252343dd9574dfe505.tar.bz2 |
Race condition patched in Email autocompletion.
Bug 3347962
Root cause of this problem: if the adapter's content gets updated by a backgroung
thread, the PopupDataSetObserver will call showDropDown which will popup the
list.
Added a flag to make this call show the popup iif it is already visible.
This relayout is needed to clear the mDataChanged flag set when the content was
modified and which otherwise prevents touch events on the result list.
ArrayAdapter didn't use its lock to protect access to mObject.
-------------------------------------------------
However, the study of the this race conditions revealed an other bug:
Updated adapter's content is not displayed in filtered AutoCompleteTextView
Bug 3369097
Change-Id: Icd90d452f98231866f4d8a1f6994c1492febecb9
Diffstat (limited to 'core/java/android/widget/ArrayAdapter.java')
-rw-r--r-- | core/java/android/widget/ArrayAdapter.java | 79 |
1 files changed, 42 insertions, 37 deletions
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java index b4ece24..593cb59 100644 --- a/core/java/android/widget/ArrayAdapter.java +++ b/core/java/android/widget/ArrayAdapter.java @@ -25,9 +25,9 @@ import android.view.ViewGroup; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.List; -import java.util.Comparator; import java.util.Collections; +import java.util.Comparator; +import java.util.List; /** * A concrete BaseAdapter that is backed by an array of arbitrary @@ -86,6 +86,8 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { private Context mContext; + // A copy of the original mObjects array, initialized from and then used instead as soon as + // the mFilter ArrayFilter is used. mObjects will then only contain the filtered values. private ArrayList<T> mOriginalValues; private ArrayFilter mFilter; @@ -170,15 +172,14 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * @param object The object to add at the end of the array. */ public void add(T object) { - if (mOriginalValues != null) { - synchronized (mLock) { + synchronized (mLock) { + if (mOriginalValues != null) { mOriginalValues.add(object); - if (mNotifyOnChange) notifyDataSetChanged(); + } else { + mObjects.add(object); } - } else { - mObjects.add(object); - if (mNotifyOnChange) notifyDataSetChanged(); } + if (mNotifyOnChange) notifyDataSetChanged(); } /** @@ -187,15 +188,14 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * @param collection The Collection to add at the end of the array. */ public void addAll(Collection<? extends T> collection) { - if (mOriginalValues != null) { - synchronized (mLock) { + synchronized (mLock) { + if (mOriginalValues != null) { mOriginalValues.addAll(collection); - if (mNotifyOnChange) notifyDataSetChanged(); + } else { + mObjects.addAll(collection); } - } else { - mObjects.addAll(collection); - if (mNotifyOnChange) notifyDataSetChanged(); } + if (mNotifyOnChange) notifyDataSetChanged(); } /** @@ -204,19 +204,18 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * @param items The items to add at the end of the array. */ public void addAll(T ... items) { - if (mOriginalValues != null) { - synchronized (mLock) { + synchronized (mLock) { + if (mOriginalValues != null) { for (T item : items) { mOriginalValues.add(item); } - if (mNotifyOnChange) notifyDataSetChanged(); - } - } else { - for (T item : items) { - mObjects.add(item); + } else { + for (T item : items) { + mObjects.add(item); + } } - if (mNotifyOnChange) notifyDataSetChanged(); } + if (mNotifyOnChange) notifyDataSetChanged(); } /** @@ -226,15 +225,14 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * @param index The index at which the object must be inserted. */ public void insert(T object, int index) { - if (mOriginalValues != null) { - synchronized (mLock) { + synchronized (mLock) { + if (mOriginalValues != null) { mOriginalValues.add(index, object); - if (mNotifyOnChange) notifyDataSetChanged(); + } else { + mObjects.add(index, object); } - } else { - mObjects.add(index, object); - if (mNotifyOnChange) notifyDataSetChanged(); } + if (mNotifyOnChange) notifyDataSetChanged(); } /** @@ -243,12 +241,12 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * @param object The object to remove. */ public void remove(T object) { - if (mOriginalValues != null) { - synchronized (mLock) { + synchronized (mLock) { + if (mOriginalValues != null) { mOriginalValues.remove(object); + } else { + mObjects.remove(object); } - } else { - mObjects.remove(object); } if (mNotifyOnChange) notifyDataSetChanged(); } @@ -257,12 +255,12 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * Remove all elements from the list. */ public void clear() { - if (mOriginalValues != null) { - synchronized (mLock) { + synchronized (mLock) { + if (mOriginalValues != null) { mOriginalValues.clear(); + } else { + mObjects.clear(); } - } else { - mObjects.clear(); } if (mNotifyOnChange) notifyDataSetChanged(); } @@ -274,7 +272,13 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { * in this adapter. */ public void sort(Comparator<? super T> comparator) { - Collections.sort(mObjects, comparator); + synchronized (mLock) { + if (mOriginalValues != null) { + Collections.sort(mOriginalValues, comparator); + } else { + Collections.sort(mObjects, comparator); + } + } if (mNotifyOnChange) notifyDataSetChanged(); } @@ -482,6 +486,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { final String[] words = valueText.split(" "); final int wordCount = words.length; + // Start at index 0, in case valueText starts with space(s) for (int k = 0; k < wordCount; k++) { if (words[k].startsWith(prefixString)) { newValues.add(value); |