列表视图中的项目正在重复

时间:2015-09-21 09:27:56

标签: android listview arraylist

我有以下arrayadapter。

public class SmsArrayAdapter extends ArrayAdapter<String> {

    List<String> smsBody;
    List<Boolean> Status;
    List<String> time;
    List<String> SmsMessageId;

    Context context;
    private static LayoutInflater inflater = null;
    String fromNumber;

    public SmsArrayAdapter(Context context, int resource, List<String> smsBody,
            List<Boolean> Status, List<String> time, List<String> SmsMessageId,
            String fromNumber) {
        super(context, resource, smsBody);
        this.smsBody = smsBody;
        this.Status = Status;
        this.context = context;
        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.fromNumber = fromNumber;
        this.time = time;
        this.SmsMessageId=SmsMessageId;
    }

    public String getStr(int position) {
        return smsBody.get(position);
    }
    public String getId(int position)
    {
        return SmsMessageId.get(position);
    }
    public void setRead(int position,String smsMessageId)
    {
        Status.set(position, true);
        ContentValues values = new ContentValues();
        values.put("read", true);
        context.getContentResolver().update(Uri.parse("content://sms/inbox"), values, "_id=" +smsMessageId, null);
    }
    @Override
    public String getItem(int position) {
        // TODO Auto-generated method stub
        return smsBody.get(position);
    }

    public static class ViewHolder {
        public TextView textfrom;
        public TextView text_sms;
        public TextView text_time;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        if (convertView == null) {

            /****** Inflate tabitem.xml file for each row ( Defined below ) *******/
            convertView = inflater.inflate(R.layout.row_item, null);

            /****** View Holder Object to contain tabitem.xml file elements ******/

            holder = new ViewHolder();

            holder.textfrom = (TextView) convertView
                    .findViewById(R.id.textView_from);
            holder.text_sms = (TextView) convertView
                    .findViewById(R.id.textView_sms);
            holder.text_time = (TextView) convertView
                    .findViewById(R.id.textView_time);

            holder.textfrom.setText(" " + fromNumber);

            String smsTextToDisplay = smsBody.get(position);
            if (smsTextToDisplay.length() > 100)
                smsTextToDisplay = smsTextToDisplay.substring(0, 99) + " ...";

            holder.text_sms.setText(smsTextToDisplay);


            holder.text_time.setText(time.get(position));
            if (Status.get(position) == false) {
                convertView.setBackgroundColor(context.getResources().getColor(
                        R.color.light_blue_overlay));

            }

            /************ Set holder with LayoutInflater ************/
            convertView.setTag(holder);
        } else
            holder = (ViewHolder) convertView.getTag();



        return convertView;
    }

}

在我的自定义列表视图中,项目正在重复。项目的位置对于所有项目都是相同的。错误在哪里?我怎样才能避免这个错误?

set adapter的代码如下:

arrayAdapter = new SmsArrayAdapter(this, R.layout.row_item, smsBody,
                status, time, SmsMessageId, fromNumber);
        smsListView.setAdapter(arrayAdapter);
        smsListView.setOnItemClickListener(this);

4 个答案:

答案 0 :(得分:0)

原因是列表视图中的视图会在滚动时被回收。像这样更改getView()

    @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            ViewHolder holder;
            if (convertView == null) {

                /****** Inflate tabitem.xml file for each row ( Defined below ) *******/
                convertView = inflater.inflate(R.layout.row_item, null);

                /****** View Holder Object to contain tabitem.xml file elements ******/

                holder = new ViewHolder();

                holder.textfrom = (TextView) convertView
                        .findViewById(R.id.textView_from);
                holder.text_sms = (TextView) convertView
                        .findViewById(R.id.textView_sms);
                holder.text_time = (TextView) convertView
                        .findViewById(R.id.textView_time);

/************ Set holder with LayoutInflater ************/
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

                holder.textfrom.setText(" " + fromNumber);

                String smsTextToDisplay = smsBody.get(position);
                if (smsTextToDisplay.length() > 100)
                    smsTextToDisplay = smsTextToDisplay.substring(0, 99) + " ...";

                holder.text_sms.setText(smsTextToDisplay);


                holder.text_time.setText(time.get(position));
                if (Status.get(position) == false) {
                    convertView.setBackgroundColor(context.getResources().getColor(
                            R.color.light_blue_overlay));

                } 

            return convertView;
        }

答案 1 :(得分:0)

这是因为您对Viewholder的实现是错误的。您没有将数据设置到回收的视图上。您可以完全删除else块,只需设置数据。

 ViewHolder holder;
    if (convertView == null) {

        /****** Inflate tabitem.xml file for each row ( Defined below ) *******/
        convertView = inflater.inflate(R.layout.row_item, null);

        /****** View Holder Object to contain tabitem.xml file elements ******/

        holder = new ViewHolder();

        holder.textfrom = (TextView) convertView
                .findViewById(R.id.textView_from);
        holder.text_sms = (TextView) convertView
                .findViewById(R.id.textView_sms);
        holder.text_time = (TextView) convertView
                .findViewById(R.id.textView_time);

        }

        /************ Set holder with LayoutInflater ************/
        convertView.setTag(holder);
    }

    holder = (ViewHolder) convertView.getTag();

    holder.textfrom.setText(" " + fromNumber);
    String smsTextToDisplay = smsBody.get(position);
    if (smsTextToDisplay.length() > 100)
        smsTextToDisplay = smsTextToDisplay.substring(0, 99) + " ...";

    holder.text_sms.setText(smsTextToDisplay);


    holder.text_time.setText(time.get(position));
    if (Status.get(position) == false) {
        convertView.setBackgroundColor(context.getResources().getColor(
                R.color.light_blue_overlay));

    return convertView;
}

此外,我建议使用RecyclerView而不是ListView。

答案 2 :(得分:0)

这是非常常见的膨胀问题,请确保您应该清除适配器中的所有条件,即对于每个 if 条件,应该有有意义的 else 条件,因为每次滚动时都会调用getView方法来回收视图。

这是我遇到同样问题时实施的方法,如果这对您没有帮助,请忽略。

谢谢

答案 3 :(得分:0)

  @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        if (convertView == null) {

            /****** Inflate tabitem.xml file for each row ( Defined below ) *******/
            convertView = inflater.inflate(R.layout.row_item, null);

            /****** View Holder Object to contain tabitem.xml file elements ******/

            holder = new ViewHolder();

            holder.textfrom = (TextView) convertView
                    .findViewById(R.id.textView_from);
            holder.text_sms = (TextView) convertView
                    .findViewById(R.id.textView_sms);
            holder.text_time = (TextView) convertView
                    .findViewById(R.id.textView_time);

            /************ Set holder with LayoutInflater ************/
            convertView.setTag(holder);
        } else{
            holder = (ViewHolder) convertView.getTag();
        }
/////////////////////Added///////////////
            holder.textfrom.setText(" " + fromNumber);

            String smsTextToDisplay = smsBody.get(position);
            if (smsTextToDisplay.length() > 100)
                smsTextToDisplay = smsTextToDisplay.substring(0, 99) + " ...";

            holder.text_sms.setText(smsTextToDisplay);


            holder.text_time.setText(time.get(position));
            if (Status.get(position) == false) {
                convertView.setBackgroundColor(context.getResources().getColor(
                        R.color.light_blue_overlay));

            }
////////Added//////////////

        return convertView;
    }