交换列表中的项目后自定义列表适配器和 ViewHolder 模式出现问题

Issue with custom list adapter and ViewHolder pattern after swaping items in list

Item 是一个自定义项 class,其中包括一个用于标题的字符串和一个用于保存复选框状态的枚举。

private final List<Item> mItems = new ArrayList<Item>();

假设我的 arraylist 中有 3 个项目,我想交换项目 2 和 3 的位置。

// Move item down
public void moveDown(int position){
    if ( position < mItems.size() -1 ) {
        Collections.swap(mItems, position, position + 1);
        notifyDataSetChanged();
    }
}

我可以看到,在调试 mItems 时,项目已正确交换。

接下来,将为每个 arraylist 项目调用 getView 函数。

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    final Item item = mItems.get(position);

    View myView = convertView;
    if ( null == myView )
    {
        LayoutInflater inflater =  LayoutInflater.from(mContext);
        myView = inflater.inflate(R.layout.item, parent, false);

        ViewHolder  viewHolder  = new ViewHolder();
        viewHolder.title        = (TextView)       myView.findViewById(R.id.titleView);
        viewHolder.statusView   = (CheckBox)       myView.findViewById(R.id.statusCheckBox);

        myView.setTag(viewHolder);
        myView.setLongClickable(true);
    }

    final ViewHolder myHolder = (ViewHolder) myView.getTag() ;

    // Display Title in TextView
    myHolder.title.setText(item.getTitle());

    // Set up Status CheckBox
    if ( item.getStatus() == Status.NOTDONE )
    {
        myHolder.statusView.setChecked(false);
    }
    else
    {
        myHolder.statusView.setChecked(true);
    }

    //  Must also set up an OnCheckedChangeListener, which is called when the user toggles the status checkbox
    myHolder.statusView
            .setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
                {
                    if ( isChecked == true ) {
                        item.setStatus(Status.DONE);
                    }
                    else
                    {
                        item.setStatus(Status.NOTDONE);
                    }
                }
            });

    return myView;

}

现在,假设在开始时,这些是项目

项目:1 |标题 A |复选框状态:未选中
项目:2 |标题 B |复选框状态:未选中
项目:3 |标题 C |复选框状态:选中

交换之后,我们得到了这个:

项目:1 |标题 A |复选框状态:未选中
项目:2 |标题 C |复选框状态:选中
项目:3 |标题 B |复选框状态:未选中

第二次 getView 被调用,因为复选框状态被选中,这将被调用:

myHolder.statusView.setChecked(true);

但奇怪的是:在那之后,我看到了对

的调用
 myHolder.statusView
   .setOnCheckedChangeListener(new OnCheckedChangeListener() {
       @Override
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
       {
           if ( isChecked == true ) {
               item.setStatus(Status.DONE);
           }
           else
           {
               item.setStatus(Status.NOTDONE);
           }
       }
   });

但是 item 指向 third item( title 'B') 和相关的复选框,所以我结束错误地将 项目 3 的状态设置为完成

在将 onCheckedChanged 侦听器设置为检查项目 3 后,我应该怎么做才能防止它为项目 3 调用?提前致谢。

您可以尝试在 class 而不是在 getview ()

中创建查看器吗

交换两个项目后,我最终重新创建了受影响的视图。 class 变量会告诉 getView() 函数何时应该重新创建视图