【问题标题】:Android ListView adding too many itemsAndroid ListView添加太多项目
【发布时间】:2015-05-22 17:52:07
【问题描述】:

我目前正在使用 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

【问题讨论】:

  • 使用标准 viewHolder 模型并在使用 viewGroup.removeAllViews() 运行您的视图添加代码之前先删除 LinearLayout 的所有视图
  • 你能给我一些代码示例吗?
  • 发布您的代码。提供建议会更有帮助。
  • 尝试将循环移动到 if (convertView == null) 块内。

标签: android for-loop android-listview android-edittext android-linearlayout


【解决方案1】:

问题是 ArrayAdapter 将在每次行变得可见时调用getView()。如果该行之前已经设置过,则会在convertView参数中传入之前设置的View。

详情请参阅here。来自the documentationconvertView

如果可能的话,要重用的旧视图。注意:你应该检查这个 view 在使用前是非空的并且是合适的类型。如果不是 可以转换此视图以显示正确的数据,此方法 可以创建一个新视图。异构列表可以指定它们的数量 视图类型,因此此视图始终是正确的类型(请参阅 getViewTypeCount() 和 getItemViewType(int))。

编辑:由于提出的原始代码引起了问题,看起来您可能无法使用标准视图持有者设计模式。您有一个独特的设置,您可以在每行中创建动态数量的项目。

您也许可以做一些稍微优化的事情,您不必在每次调用 getView() 时调用 inflate(),但仍然在每次调用 getView() 时重新创建 ViewHolder,为了在滚动时填充正确的数据:

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;
    }

【讨论】:

  • @Broadwell 当然,没问题!
  • 所以现在我遇到的问题是它不会显示我的所有数据。假设我有 10 个条目要显示在列表视图中,它只获取前 4 个的数据并一遍又一遍地显示,直到显示所有 10 个条目。标题会正常显示。基本上它会一遍又一遍地显示前 4 个条目,而不是 10 个中的每一个
  • @Broadwell 这很奇怪。听起来您的数据源可能有问题,无论您在此适配器中传递给List&lt;RowItem&gt; items 什么。尝试验证列表是否包含您期望的内容。如果您无法解决问题,请发布一个新问题,我会看看!
  • 我仔细检查了数据,它包含了我想要的一切。我还注意到在前 4 个列表之后 convertView 不再为空。无论如何,这是新问题stackoverflow.com/questions/30410333/…
猜你喜欢
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多