Merge "Race condition patched in Email autocompletion." into honeycomb
This commit is contained in:
committed by
Android (Google) Code Review
commit
0c44d1dbb1
@@ -817,7 +817,7 @@ public interface WindowManager extends ViewManager {
|
||||
public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
|
||||
|
||||
/**
|
||||
* Desired operating mode for any soft input area. May any combination
|
||||
* Desired operating mode for any soft input area. May be any combination
|
||||
* of:
|
||||
*
|
||||
* <ul>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.widget;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.DataSetObserver;
|
||||
@@ -36,8 +38,6 @@ import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
|
||||
/**
|
||||
* <p>An editable text view that shows completion suggestions automatically
|
||||
@@ -113,6 +113,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
|
||||
|
||||
private Validator mValidator = null;
|
||||
|
||||
// Set to true when text is set directly and no filtering shall be performed
|
||||
private boolean mBlockCompletion;
|
||||
|
||||
private PassThroughClickListener mPassThroughClickListener;
|
||||
@@ -721,6 +722,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
|
||||
return;
|
||||
}
|
||||
|
||||
updateList();
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
// the drop down is shown only when a minimum number of characters
|
||||
// was typed in the text view
|
||||
if (enoughToFilter()) {
|
||||
@@ -840,7 +845,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
|
||||
|
||||
mBlockCompletion = true;
|
||||
replaceText(convertSelectionToString(selectedItem));
|
||||
mBlockCompletion = false;
|
||||
mBlockCompletion = false;
|
||||
|
||||
if (mItemClickListener != null) {
|
||||
final ListPopupWindow list = mPopup;
|
||||
@@ -903,10 +908,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onFilterComplete(int count) {
|
||||
updateDropDownForFilter(count);
|
||||
updateDropDownForFilter(count, true);
|
||||
}
|
||||
|
||||
private void updateDropDownForFilter(int count) {
|
||||
private void updateDropDownForFilter(int count, boolean forceShow) {
|
||||
// Not attached to window, don't update drop-down
|
||||
if (getWindowVisibility() == View.GONE) return;
|
||||
|
||||
@@ -919,7 +924,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
|
||||
|
||||
final boolean dropDownAlwaysVisible = mPopup.isDropDownAlwaysVisible();
|
||||
if ((count > 0 || dropDownAlwaysVisible) && enoughToFilter()) {
|
||||
if (hasFocus() && hasWindowFocus()) {
|
||||
if (hasFocus() && hasWindowFocus() && (forceShow || isPopupShowing())) {
|
||||
showDropDown();
|
||||
}
|
||||
} else if (!dropDownAlwaysVisible) {
|
||||
@@ -1182,12 +1187,14 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
|
||||
// If the popup is not showing already, showing it will cause
|
||||
// the list of data set observers attached to the adapter to
|
||||
// change. We can't do it from here, because we are in the middle
|
||||
// of iterating throught he list of observers.
|
||||
// of iterating through the list of observers.
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
final ListAdapter adapter = mAdapter;
|
||||
if (adapter != null) {
|
||||
updateDropDownForFilter(adapter.getCount());
|
||||
// This will re-layout, thus resetting mDataChanged, so that the
|
||||
// listView click listener stays responsive
|
||||
updateDropDownForFilter(adapter.getCount(), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user