Android ListView 添加太多项目

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

我目前正在使用 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了解详情。来自 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)).

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

您也许可以做一些稍微优化的事情,这样您就不必在每次调用 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() 时完全重新创建 View :

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

关于Android ListView 添加太多项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30402985/

相关文章:

android - 相对于旋转角度的矩形坐标

运行前台服务的 Android 'BadTokenException window token android.os.BinderProxy@4250d6d8 is not valid'

java - 如何在 jLabel 的 for 循环中显示数字?

android - android.performFiltering() 过滤时出现 sql 异常。

android - 如何更改自定义 ListView 项目布局中按钮的可见性

java - 这段代码有什么问题,数字溢出警告

android - Meteor:一个后端 - 多个不同的前端 2x web 和 1x mobile

c++ - 对基于范围的for循环的误解?

javascript - 这是否适合我的循环?

android - ListView 在 2.x 上改变颜色