交换列表中的项目后自定义列表适配器和 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() 函数何时应该重新创建视图
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() 函数何时应该重新创建视图