android - 为什么当我向上或向下滚动列表时它会在我的自定义光标适配器中激活一个 Switch 监听器?

标签 android

我可以通过已实现和调试的 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/

相关文章:

java - Android 是否有字符串的实习生字符限制?

滚动 ListView 时Android ActionBar隐藏/显示

android - 用于SpringAndroid库的Android Proguard配置

android - 如何在 Jetpack Compose 中管理焦点状态

android - LazyColumnFor 中的 OnScrolled (Jetpack Compose)

android - 任何人都有 MediaRecorder 使用 ParcelFileDescriptor 和 createPipe()?

java - 提取 Android Java 源代码中使用的方法

java - 为什么在 Java 中使用静态辅助方法不好?

javascript - 在我的 Android WebView 上显示的每个页面上导入 Javascript

android - 如何让用户取消 Android 中的进度通知?