Fix race condition.
Crash was reported where the checked item position had yet to be
set when the list tried to get it. This uses a listener to make sure
that the checked item isnt set in the list until the adapter has it.
Change-Id: I2b5170ab9440bbb0a69989657313b1a4b6d653cd
diff --git a/src/com/android/ex/chips/RecipientAlternatesAdapter.java b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
index 3d2c87b..792fdcc 100644
--- a/src/com/android/ex/chips/RecipientAlternatesAdapter.java
+++ b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
@@ -37,7 +37,10 @@
private int mCheckedItemPosition = -1;
- public RecipientAlternatesAdapter(Context context, long contactId, long currentId, int viewId) {
+ private OnCheckedItemChangedListener mCheckedItemChangedListener;
+
+ public RecipientAlternatesAdapter(Context context, long contactId, long currentId, int viewId,
+ OnCheckedItemChangedListener listener) {
super(context, context.getContentResolver().query(Email.CONTENT_URI, EmailQuery.PROJECTION,
Email.CONTACT_ID + " =?", new String[] {
String.valueOf(contactId)
@@ -45,6 +48,7 @@
mLayoutInflater = LayoutInflater.from(context);
mLayoutId = viewId;
mCurrentId = currentId;
+ mCheckedItemChangedListener = listener;
}
@Override
@@ -71,6 +75,9 @@
}
if (cursor.getLong(EmailQuery.DATA_ID) == mCurrentId) {
mCheckedItemPosition = position;
+ if (mCheckedItemChangedListener != null) {
+ mCheckedItemChangedListener.onCheckedItemChanged(mCheckedItemPosition);
+ }
}
bindView(convertView, convertView.getContext(), cursor);
return convertView;
@@ -109,10 +116,7 @@
return mLayoutInflater.inflate(mLayoutId, null);
}
- /**
- * Get the position of the item that should be checked.
- */
- public int getCheckedItemPosition() {
- return mCheckedItemPosition;
+ /*package*/ static interface OnCheckedItemChangedListener {
+ public void onCheckedItemChanged(int position);
}
}
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index 7cda831..9819e02 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -921,7 +921,8 @@
* RecipientChip defines an ImageSpan that contains information relevant to
* a particular recipient.
*/
- public class RecipientChip extends ImageSpan implements OnItemClickListener {
+ public class RecipientChip extends ImageSpan implements OnItemClickListener,
+ RecipientAlternatesAdapter.OnCheckedItemChangedListener {
private final CharSequence mDisplay;
private final CharSequence mValue;
@@ -944,6 +945,8 @@
private ListPopupWindow mAlternatesPopup;
+ private int mCheckedItem;
+
public RecipientChip(Drawable drawable, RecipientEntry entry, int offset) {
super(drawable);
mDisplay = entry.getDisplayName();
@@ -1159,8 +1162,9 @@
int bottom = calculateLineBottom(xy[1], line, (int) mChipHeight);
mAnchorView.setBottom(bottom);
mAnchorView.setTop(bottom);
- mAlternatesAdapter = new RecipientAlternatesAdapter(getContext(),
- mEntry.getContactId(), mEntry.getDataId(), mAlternatesLayout);
+ mCheckedItem = -1;
+ mAlternatesAdapter = new RecipientAlternatesAdapter(getContext(), mEntry
+ .getContactId(), mEntry.getDataId(), mAlternatesLayout, this);
// Align the alternates popup with the left side of the View, regardless
// of the position of the chip tapped.
mAlternatesPopup.setAnchorView(mAnchorView);
@@ -1170,7 +1174,23 @@
mAlternatesPopup.show();
ListView listView = mAlternatesPopup.getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- listView.setItemChecked(mAlternatesAdapter.getCheckedItemPosition(), true);
+ // Checked item would be -1 if the adapter has not
+ // loaded the view that should be checked yet. The
+ // variable will be set correctly when onCheckedItemChanged
+ // is called in a separate thread.
+ if (mCheckedItem != -1) {
+ listView.setItemChecked(mCheckedItem, true);
+ }
+ }
+ }
+
+ @Override
+ public void onCheckedItemChanged(int position) {
+ ListView listView = mAlternatesPopup.getListView();
+ if (listView != null && listView.getCheckedItemCount() == 0) {
+ listView.setItemChecked(position, true);
+ } else {
+ mCheckedItem = position;
}
}