Android ListView:对项目所做的更改会影响其他项目
Android ListView: Changes made to Items affect other Items
我知道这是使用 ListView 时经常遇到的问题。但是,我没有发现我的实现有任何问题,因为我已经正确地遵循了自定义适配器的 ViewHolder 模式。
问题:
对项目所做的更改,例如一次性更改文本视图的文本,会在滚动时影响其他随机项目down/up。当我向上滚动时,原始项目和其他项目都发生了变化。
这个问题可以通过 ViewHolder 模式来解决。这很奇怪,因为我仍然遇到问题!
适配器代码:
public class TrackerAdapter extends BaseAdapter {
private Activity activity;
private static LayoutInflater inflater = null;
ArrayList <Set> sets = new ArrayList <> ();
public TrackerAdapter(Activity a, final ArrayList <Set> sets) {
this.activity = a;
this.inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.sets = sets;
}
public int getCount() {
return sets.size();
}
public Set getItem(int position) {
return sets.get(position);
}
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final Set set = sets.get(position);
final Holder holder;
try {
if (view == null) {
view = inflater.inflate(R.layout.row_single, null);
holder = new Holder();
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.name.setText(set.getUser().getName());
} catch (Exception ex) {
Log.d("CHECK", "Error at TrackerAdapter");
Log.d("CHECK", Log.getStackTraceString(ex));
}
return view;
}
public static class Holder {
TextView name;
}
}
您在我的代码中发现了什么问题?我是否正确实施了 ViewHolder 模式?
通过使用阵列适配器
Holder holder = new Holder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_single, null);
holder.name = (TextView) view.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.set = getItem(position);
holder.name.setText(holder.set.getUser().getName());
public static class Holder {
TextView name;
Set set;
}
通过使用基础适配器
Holder holder = new Holder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_single, null);
holder.name = (TextView) view.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.name.setText(sets.get(position).getName());
public static class Holder {
TextView name;
}
您更改 TextView 文本的方式是什么?就在 TextView 本身或 ArrayList 的相应项中,然后 adapter.notifyDataSetChanged()?
还有一件奇怪的事。 getViewTypeCount() return 是您希望在列表中扩充的 XML 的数量。如果你只有 1 xml,return 1 是可以的(但是,对于我来说,当它是 1 时,明确地写这个方法是多余的)。但是在 getItemViewType() 中,您应该根据项目获得一种或另一种 viewType 来编写条件。而你 return 当前位置,最好修复它:)
您的代码看起来是正确的,所以我要大胆猜测,并说您从外部修改了支持 ArrayList
。进行更改后,如果不通知 ListView
,您将无法执行此操作。
以下代码将解耦您的工作数组和显示的数据。
final ArrayList <Set> sets = new ArrayList <> ();
public TrackerAdapter() {
}
public void setItems(ArrayList<Set> sets) {
this.sets.clear();
this.sets.addAll(sets)
notifyDataSetChanged();
}
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final Set set = sets.get(position);
final Holder holder;
if (view == null) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.row_single, parent, false);
holder = new Holder();
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.name.setText(set.getUser().getName());
return view;
}
我知道这是使用 ListView 时经常遇到的问题。但是,我没有发现我的实现有任何问题,因为我已经正确地遵循了自定义适配器的 ViewHolder 模式。
问题:
对项目所做的更改,例如一次性更改文本视图的文本,会在滚动时影响其他随机项目down/up。当我向上滚动时,原始项目和其他项目都发生了变化。
这个问题可以通过 ViewHolder 模式来解决。这很奇怪,因为我仍然遇到问题!
适配器代码:
public class TrackerAdapter extends BaseAdapter {
private Activity activity;
private static LayoutInflater inflater = null;
ArrayList <Set> sets = new ArrayList <> ();
public TrackerAdapter(Activity a, final ArrayList <Set> sets) {
this.activity = a;
this.inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.sets = sets;
}
public int getCount() {
return sets.size();
}
public Set getItem(int position) {
return sets.get(position);
}
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final Set set = sets.get(position);
final Holder holder;
try {
if (view == null) {
view = inflater.inflate(R.layout.row_single, null);
holder = new Holder();
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.name.setText(set.getUser().getName());
} catch (Exception ex) {
Log.d("CHECK", "Error at TrackerAdapter");
Log.d("CHECK", Log.getStackTraceString(ex));
}
return view;
}
public static class Holder {
TextView name;
}
}
您在我的代码中发现了什么问题?我是否正确实施了 ViewHolder 模式?
通过使用阵列适配器
Holder holder = new Holder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_single, null);
holder.name = (TextView) view.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.set = getItem(position);
holder.name.setText(holder.set.getUser().getName());
public static class Holder {
TextView name;
Set set;
}
通过使用基础适配器
Holder holder = new Holder();
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_single, null);
holder.name = (TextView) view.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.name.setText(sets.get(position).getName());
public static class Holder {
TextView name;
}
您更改 TextView 文本的方式是什么?就在 TextView 本身或 ArrayList 的相应项中,然后 adapter.notifyDataSetChanged()?
还有一件奇怪的事。 getViewTypeCount() return 是您希望在列表中扩充的 XML 的数量。如果你只有 1 xml,return 1 是可以的(但是,对于我来说,当它是 1 时,明确地写这个方法是多余的)。但是在 getItemViewType() 中,您应该根据项目获得一种或另一种 viewType 来编写条件。而你 return 当前位置,最好修复它:)
您的代码看起来是正确的,所以我要大胆猜测,并说您从外部修改了支持 ArrayList
。进行更改后,如果不通知 ListView
,您将无法执行此操作。
以下代码将解耦您的工作数组和显示的数据。
final ArrayList <Set> sets = new ArrayList <> ();
public TrackerAdapter() {
}
public void setItems(ArrayList<Set> sets) {
this.sets.clear();
this.sets.addAll(sets)
notifyDataSetChanged();
}
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final Set set = sets.get(position);
final Holder holder;
if (view == null) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.row_single, parent, false);
holder = new Holder();
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.name.setText(set.getUser().getName());
return view;
}