Android ListView 添加了太多项目
Android ListView adding too many items
我目前正在使用 for 循环在 ListView 元素内的 LinearLayout 内添加 TextView,因为我必须在其中添加的 TextView 的数量是可变的。我像往常一样将项目添加到 ListViews。
问题是,当我滚动时,项目开始变得越来越多,而当我向上滚动时,我最终得到数百个项目。我认为这是因为 ListView 正在重新加载并再次循环通过 for 循环,因此多次添加每个 TextView。我能阻止吗?
我的代码:
public class ListViewAdapter extends ArrayAdapter<RowItem> {
private final Context context;
public ListViewAdapter(Context context, List<RowItem> items) {
super(context, R.layout.list, items);
this.context = context;
}
private class ViewHolder {
TextView title;
LinearLayout linearLayout;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_list, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.list_line);
holder.linearLayout = (LinearLayout) convertView.findViewById(R.id.list_linear);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(rowItem.getTitle());
String data = rowItem.getData();
String[] split0 = data.split("=");
Log.e("DATA", data);
Log.e("LINE", rowItem.getTitle());
for (int j = 0; j < split0.length; j++) {
String[] split1 = split0[j].split(":");
LinearLayout parentLayout = new LinearLayout(MainActivity.context);
parentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parentLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int k = 0; k < split1.length; k++) {
TextView textView = new TextView(MainActivity.context);
textView.setText(split1[k]);
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
textView.setTextSize(18);
parentLayout.addView(textView);
}
holder.linearLayout.addView(parentLayout);
}
return convertView;
}
}
对于一个条目,我的数据方案如下所示:
text1:text2=text3:text4
它在列表中的显示方式:
text1 text2
text3 text4
问题是每次行变为可见时 ArrayAdapter 都会调用 getView()
。如果该行之前设置过,则在convertView
参数中传入之前设置的View
参见 here for details. From the documentation convertView
:
The old view to reuse, if possible. Note: You should check that this
view is non-null and of an appropriate type before using. If it is not
possible to convert this view to display the correct data, this method
can create a new view. Heterogeneous lists can specify their number of
view types, so that this View is always of the right type (see
getViewTypeCount() and getItemViewType(int)).
编辑:由于最初提出的代码引起了问题,看起来您可能最终无法使用标准视图持有者设计模式。您有一个独特的设置,您在每行中创建动态数量的项目。
您可以做一些稍微优化的事情,您不必在每次 getView()
调用时调用 inflate()
,但仍然重新创建 ViewHolder
每次调用 getView()
时,为了在滚动时填充正确的数据:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_list, null);
}
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.list_line);
holder.linearLayout = (LinearLayout) convertView.findViewById(R.id.list_linear);
convertView.setTag(holder);
holder.title.setText(rowItem.getTitle());
String data = rowItem.getData();
String[] split0 = data.split("=");
Log.e("DATA", data);
Log.e("LINE", rowItem.getTitle());
for (int j = 0; j < split0.length; j++) {
String[] split1 = split0[j].split(":");
LinearLayout parentLayout = new LinearLayout(MainActivity.context);
parentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parentLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int k = 0; k < split1.length; k++) {
TextView textView = new TextView(MainActivity.context);
textView.setText(split1[k]);
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
textView.setTextSize(18);
parentLayout.addView(textView);
}
holder.linearLayout.addView(parentLayout);
}
return convertView;
}
如果这不起作用,您可以回到基础,在每次调用 getView()
:
时完全重新创建视图
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
//if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_list, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.list_line);
holder.linearLayout = (LinearLayout) convertView.findViewById(R.id.list_linear);
convertView.setTag(holder);
holder.title.setText(rowItem.getTitle());
String data = rowItem.getData();
String[] split0 = data.split("=");
Log.e("DATA", data);
Log.e("LINE", rowItem.getTitle());
for (int j = 0; j < split0.length; j++) {
String[] split1 = split0[j].split(":");
LinearLayout parentLayout = new LinearLayout(MainActivity.context);
parentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parentLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int k = 0; k < split1.length; k++) {
TextView textView = new TextView(MainActivity.context);
textView.setText(split1[k]);
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
textView.setTextSize(18);
parentLayout.addView(textView);
}
holder.linearLayout.addView(parentLayout);
}
//}
return convertView;
}
我目前正在使用 for 循环在 ListView 元素内的 LinearLayout 内添加 TextView,因为我必须在其中添加的 TextView 的数量是可变的。我像往常一样将项目添加到 ListViews。 问题是,当我滚动时,项目开始变得越来越多,而当我向上滚动时,我最终得到数百个项目。我认为这是因为 ListView 正在重新加载并再次循环通过 for 循环,因此多次添加每个 TextView。我能阻止吗?
我的代码:
public class ListViewAdapter extends ArrayAdapter<RowItem> {
private final Context context;
public ListViewAdapter(Context context, List<RowItem> items) {
super(context, R.layout.list, items);
this.context = context;
}
private class ViewHolder {
TextView title;
LinearLayout linearLayout;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_list, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.list_line);
holder.linearLayout = (LinearLayout) convertView.findViewById(R.id.list_linear);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(rowItem.getTitle());
String data = rowItem.getData();
String[] split0 = data.split("=");
Log.e("DATA", data);
Log.e("LINE", rowItem.getTitle());
for (int j = 0; j < split0.length; j++) {
String[] split1 = split0[j].split(":");
LinearLayout parentLayout = new LinearLayout(MainActivity.context);
parentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parentLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int k = 0; k < split1.length; k++) {
TextView textView = new TextView(MainActivity.context);
textView.setText(split1[k]);
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
textView.setTextSize(18);
parentLayout.addView(textView);
}
holder.linearLayout.addView(parentLayout);
}
return convertView;
}
}
对于一个条目,我的数据方案如下所示:
text1:text2=text3:text4
它在列表中的显示方式:
text1 text2
text3 text4
问题是每次行变为可见时 ArrayAdapter 都会调用 getView()
。如果该行之前设置过,则在convertView
参数中传入之前设置的View
参见 here for details. From the documentation convertView
:
The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).
编辑:由于最初提出的代码引起了问题,看起来您可能最终无法使用标准视图持有者设计模式。您有一个独特的设置,您在每行中创建动态数量的项目。
您可以做一些稍微优化的事情,您不必在每次 getView()
调用时调用 inflate()
,但仍然重新创建 ViewHolder
每次调用 getView()
时,为了在滚动时填充正确的数据:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_list, null);
}
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.list_line);
holder.linearLayout = (LinearLayout) convertView.findViewById(R.id.list_linear);
convertView.setTag(holder);
holder.title.setText(rowItem.getTitle());
String data = rowItem.getData();
String[] split0 = data.split("=");
Log.e("DATA", data);
Log.e("LINE", rowItem.getTitle());
for (int j = 0; j < split0.length; j++) {
String[] split1 = split0[j].split(":");
LinearLayout parentLayout = new LinearLayout(MainActivity.context);
parentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parentLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int k = 0; k < split1.length; k++) {
TextView textView = new TextView(MainActivity.context);
textView.setText(split1[k]);
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
textView.setTextSize(18);
parentLayout.addView(textView);
}
holder.linearLayout.addView(parentLayout);
}
return convertView;
}
如果这不起作用,您可以回到基础,在每次调用 getView()
:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
//if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_list, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.list_line);
holder.linearLayout = (LinearLayout) convertView.findViewById(R.id.list_linear);
convertView.setTag(holder);
holder.title.setText(rowItem.getTitle());
String data = rowItem.getData();
String[] split0 = data.split("=");
Log.e("DATA", data);
Log.e("LINE", rowItem.getTitle());
for (int j = 0; j < split0.length; j++) {
String[] split1 = split0[j].split(":");
LinearLayout parentLayout = new LinearLayout(MainActivity.context);
parentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parentLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int k = 0; k < split1.length; k++) {
TextView textView = new TextView(MainActivity.context);
textView.setText(split1[k]);
textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
textView.setTextSize(18);
parentLayout.addView(textView);
}
holder.linearLayout.addView(parentLayout);
}
//}
return convertView;
}