交换列表中的项目后自定义列表适配器和 ViewHolder 模式出现问题
Posted
技术标签:
【中文标题】交换列表中的项目后自定义列表适配器和 ViewHolder 模式出现问题【英文标题】:Issue with custom list adapter and ViewHolder pattern after swaping items in list 【发布时间】:2015-07-16 16:16:51 【问题描述】:Item 是一个自定义类,其中包含一个标题字符串和一个用于保存复选框状态的枚举。
private final List<Item> mItems = new ArrayList<Item>();
假设我的数组列表中有 3 个项目,我想交换项目 2 和 3 的位置。
// Move item down
public void moveDown(int position)
if ( position < mItems.size() -1 )
Collections.swap(mItems, position, position + 1);
notifyDataSetChanged();
我可以看到,在调试 mItems 时,项目已正确交换。
接下来,将为每个数组列表项调用 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 指向 第三个项目(标题 'B')和相关的复选框,所以我最终错误地设置了 item 的状态3 完成
在我将 onCheckedChanged 侦听器设置为检查第 3 项后,我应该怎么做才能防止调用第 3 项?提前致谢。
【问题讨论】:
不使用view holder会发生这种情况吗? @pskink 不,它只在我使用 ViewHolder 时发生。如果我去掉 if ( null == myView ),那么行为看起来还可以 不,你不能删除“if (null == myView)”,它是为了视图重用,只是删除视图持有者模式,这是一个神话,它提高了性能,但几乎总是引入问题 【参考方案1】:你能不能尝试在class而不是getview()中创建viewholder
【讨论】:
我不太明白,你能改写一下吗?【参考方案2】:在交换两个项目后,我最终重新创建了受影响的视图。类变量会告诉 getView() 函数何时应该重新创建视图
【讨论】:
以上是关于交换列表中的项目后自定义列表适配器和 ViewHolder 模式出现问题的主要内容,如果未能解决你的问题,请参考以下文章