summaryrefslogtreecommitdiff
path: root/core/java/android/widget/AutoCompleteTextView.java
diff options
context:
space:
mode:
authorYigit Boyar <yboyar@google.com>2014-08-25 13:27:40 -0700
committerYigit Boyar <yboyar@google.com>2014-08-27 13:31:24 -0700
commit6490644b4d37667a73d2e48450d1de9297c3bf0b (patch)
treec6abb4d2d360a488d26d22a19a7f2c5229819aff /core/java/android/widget/AutoCompleteTextView.java
parent1a95b1a6f3d1c2ed237fd678e1d8c88c2aae97df (diff)
Use a weak observable in AutoCompleteTextView
If adapter has longer life span than AutoCompleteTextView, it may leak the View. This change prevents it by using a static observer with a weak reference to the actual TextView. Bug: 11287688 Change-Id: I2c9db94dfa1be3b3f5368406e557f3e8e34bbce9
Diffstat (limited to 'core/java/android/widget/AutoCompleteTextView.java')
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java48
1 files changed, 33 insertions, 15 deletions
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index eb232fd8db5c..add0de3aa8f9 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -35,9 +35,8 @@ import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-
import com.android.internal.R;
-
+import java.lang.ref.WeakReference;
/**
* <p>An editable text view that shows completion suggestions automatically
@@ -629,7 +628,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
*/
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
if (mObserver == null) {
- mObserver = new PopupDataSetObserver();
+ mObserver = new PopupDataSetObserver(this);
} else if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
@@ -1255,25 +1254,44 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
}
}
- private class PopupDataSetObserver extends DataSetObserver {
+ /**
+ * Static inner listener that keeps a WeakReference to the actual AutoCompleteTextView.
+ * <p>
+ * This way, if adapter has a longer life span than the View, we won't leak the View, instead
+ * we will just leak a small Observer with 1 field.
+ */
+ private static class PopupDataSetObserver extends DataSetObserver {
+ private final WeakReference<AutoCompleteTextView> mViewReference;
+
+ private PopupDataSetObserver(AutoCompleteTextView view) {
+ mViewReference = new WeakReference<AutoCompleteTextView>(view);
+ }
+
@Override
public void onChanged() {
- if (mAdapter != null) {
+ final AutoCompleteTextView textView = mViewReference.get();
+ if (textView != null && textView.mAdapter != null) {
// 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 through the list of observers.
- post(new Runnable() {
- public void run() {
- final ListAdapter adapter = mAdapter;
- if (adapter != null) {
- // This will re-layout, thus resetting mDataChanged, so that the
- // listView click listener stays responsive
- updateDropDownForFilter(adapter.getCount());
- }
- }
- });
+ textView.post(updateRunnable);
}
}
+
+ private final Runnable updateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ final AutoCompleteTextView textView = mViewReference.get();
+ if (textView == null) {
+ return;
+ }
+ final ListAdapter adapter = textView.mAdapter;
+ if (adapter == null) {
+ return;
+ }
+ textView.updateDropDownForFilter(adapter.getCount());
+ }
+ };
}
}