我可以通过已实现和调试的 toast 看到,当我在列表上向上或向下滚动时,我的监听器会调用 onCheckedChanged 方法。我正在回收 View ( View 持有者模式)并且可以想象 View 的回收会导致问题但不确定该怎么做。这是自定义光标适配器的代码 -
public class MyCursorAdapter extends CursorAdapter {
private Context mContext;
private LayoutInflater cursorInflater;
private int res;
private String mgName;
private String mMfg;
private String mRarity;
private String mLoosePrice;
private String mgYear;
private String mYear_Mfg;
private int mOwned;
private boolean isOwned;
private Switch mySwitch;
private String mID;
private String mIDfinal;
private View v;
private int position = 1;
public MyCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
cursorInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mContext = context;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
v = cursorInflater.inflate(R.layout.fragment_list, viewGroup, false);
ViewHolder holder = new ViewHolder();
holder.imageView = (ImageView) v.findViewById(R.id.game);
holder.textView1 = (TextView) v.findViewById(R.id.game_Title);
holder.textView2 = (TextView) v.findViewById(R.id.game_mfg);
holder.textView3 = (TextView) v.findViewById(R.id.rarity_value);
holder.textView4 = (TextView) v.findViewById(R.id.loose_cart_value);
holder.switch1 = (Switch) v.findViewById(R.id.owned_switch);
v.setTag(holder);
return v;
}
@Override
public void bindView(final View view, Context context, Cursor cursor) {
//Determines row colors
if (position % 2 == 1) {
view.setBackgroundColor(Color.parseColor("#bbbbbb"));
position++;
} else {
view.setBackgroundColor(Color.parseColor("#7b7b7b"));
position++;
}
if (position > 10) {
position = 1;
}
ViewHolder holder = (ViewHolder) view.getTag();
String mboxArt = cursor.getString(cursor.getColumnIndex("_id"));
mboxArt = "a" + mboxArt;
res = context.getResources().getIdentifier(mboxArt, "drawable", context.getPackageName());
mgName = cursor.getString(cursor.getColumnIndex("gName"));
mMfg = cursor.getString(cursor.getColumnIndex("mfg"));
mgYear = cursor.getString(cursor.getColumnIndex("gYear"));
mYear_Mfg = mMfg + "," + mgYear;
mRarity = cursor.getString(cursor.getColumnIndex("rarity"));
mOwned = cursor.getInt(cursor.getColumnIndex("cart"));
mLoosePrice = cursor.getString(cursor.getColumnIndex("lPrice"));
// mID = cursor.getString(cursor.getColumnIndex("My_Collection_T._id"));
// mIDfinal = "'" + mID + "'";
if (mOwned == 1) {
isOwned = true;
} else {
isOwned = false;
}
view.setTag(holder);
holder.imageView.setImageResource(res);
holder.textView1.setText(mgName);
holder.textView2.setText(mYear_Mfg);
holder.textView3.setText(mRarity);
holder.textView4.setText(mLoosePrice);
holder.switch1.setChecked(isOwned);
//Listener for owned switch
mySwitch = (Switch) view.findViewById(R.id.owned_switch);
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ContentValues mNewValues = new ContentValues();
TextView gameN = (TextView) view.findViewById(R.id.game_Title);
CharSequence text = gameN.getText();
text = "'" + text + "'";
String gameName = text.toString();
if (buttonView.isChecked()) {
mNewValues.put("cart", 1);
mNewValues.put("numCart", 1);
gameName = "gName = " + gameName;
mContext.getContentResolver().update(GamesContract.My_Collection_T.CONTENT_URI, mNewValues, gameName, null);
ContentResolver resolver = mContext.getContentResolver();
Cursor c = resolver.query(GamesContract.My_Collection_T.CONTENT_URI, null, null, null, null);
//For debugging -
if (c != null) {
StringBuilder sb = new StringBuilder();
dumpCursor(c, sb);
String result = sb.toString();
Toast.makeText(mContext,
result,
Toast.LENGTH_LONG
).show();
c.close();
}
/////////////////////////
mContext.getContentResolver().notifyChange(GamesContract.My_Collection_T.CONTENT_URI, null);
} else {
mNewValues.put("cart", 0);
mNewValues.put("numCart", 0);
gameName = "gName = " + gameName;
mContext.getContentResolver().update(GamesContract.My_Collection_T.CONTENT_URI, mNewValues, gameName, null);
ContentResolver resolver = mContext.getContentResolver();
Cursor c = resolver.query(GamesContract.My_Collection_T.CONTENT_URI, null, null, null, null);
//For debugging
if (c != null) {
StringBuilder sb = new StringBuilder();
dumpCursor(c, sb);
String result = sb.toString();
Toast.makeText(mContext,
result,
Toast.LENGTH_LONG
).show();
c.close();
}
/////////////////////////////////////////////
mContext.getContentResolver().notifyChange(GamesContract.My_Collection_T.CONTENT_URI, null);
}
}
});
}
static class ViewHolder {
ImageView imageView;
TextView textView1;
TextView textView2;
TextView textView3;
TextView textView4;
Switch switch1;
}
}
最佳答案
不幸的是,调用 setChecked(boolean)
会触发监听器,即使您以编程方式进行也是如此。也就是说,无法知道用户是否单击了它或者您是否以编程方式更改了状态。
由于 View 被回收,第一次创建 View 时,owned_switch
没有附加监听器。然后设置状态:
holder.switch1.setChecked(isOwned);
然后附加一个监听器:
mySwitch.setOnCheckedChangeListener(...);
一切都按预期进行。但是,在 View 被回收后,它仍然附加了监听器(与 getView()
中的 convertView
返回相同的 View
),所以调用:
holder.switch1.setChecked(isOwned);
将触发您之前在 View 上设置的原始监听器。一种简单的解决方法是在调整选中状态和重置监听器之前取消监听器:
mySwitch.setOnCheckedChangeListener(null);
holder.switch1.setChecked(isOwned);
mySwitch.setOnCheckedChangeListener(...);
另外,不确定为什么要为 mySwitch
创建一个新变量,因为它与 holder.switch1
的 View 相同。
关于android - 为什么当我向上或向下滚动列表时它会在我的自定义光标适配器中激活一个 Switch 监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25798089/