diff options
| author | Yigit Boyar <yboyar@google.com> | 2014-08-25 13:27:40 -0700 |
|---|---|---|
| committer | Yigit Boyar <yboyar@google.com> | 2014-08-27 13:31:24 -0700 |
| commit | 6490644b4d37667a73d2e48450d1de9297c3bf0b (patch) | |
| tree | c6abb4d2d360a488d26d22a19a7f2c5229819aff /core/java/android/widget/AutoCompleteTextView.java | |
| parent | 1a95b1a6f3d1c2ed237fd678e1d8c88c2aae97df (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.java | 48 |
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()); + } + }; } } |
