滚动时更改列表视图内容

Changing List View contents when scrolling

我正在尝试在列表视图中显示收件箱中的所有短信。

问题:

当我启动 Activity 时,消息在列表视图中正确填充。但是当我向上或向下滚动时 some 消息的内容在 middlecorner 位置被改变自动地。我无法追查列表这种异常行为的原因。您能看看适配器 class 或代码的其他部分有什么问题吗?

代码:

我正在使用以下自定义适配器来填充 ListView。

import java.util.*;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class ListViewAdapter extends BaseAdapter {

    private String FIRST_COLUMN = "First";
    private String SECOND_COLUMN = "Second";
    private String THIRD_COLUMN = "Third";
    private String FOURTH_COLUMN = "Fourth";
    private String FIFTH_COLUMN = "Fifth";
    private String SIXTH_COLUMN = "Sixth";
    String class_name="";

    public ArrayList<HashMap<String, String>> list;
    Activity activity;
    TextView txtFirst;
    TextView txtSecond;
    TextView txtThird;
    TextView txtFourth;
    TextView txtFifth;
    TextView txtSixth;

    public ListViewAdapter(Activity activity,
                           ArrayList<HashMap<String, String>> list) {
        super();
        this.activity = activity;
        this.list = list;
        class_name = activity.getClass().toString();

    }

    @Override
    public int getCount() {

        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

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

        LayoutInflater inflater = activity.getLayoutInflater();
        if (convertView == null) {  
                convertView = inflater.inflate(R.layout.messages_row, null);
                txtFirst = (TextView) convertView.findViewById(R.id.tvMsgId_msg);
                txtSecond = (TextView) convertView.findViewById(R.id.tvCtId_msg);
                txtThird = (TextView) convertView.findViewById(R.id.tvCtName_msg);
                txtFourth = (TextView) convertView.findViewById(R.id.tvCtNo_msg);
                txtFifth = (TextView) convertView.findViewById(R.id.tvMsgDate_msg);
                txtSixth = (TextView) convertView.findViewById(R.id.tvSms_msg);
        }

        HashMap<String, String> map = list.get(position);
        txtFirst.setText(map.get(FIRST_COLUMN));
        txtSecond.setText(map.get(SECOND_COLUMN));
        txtThird.setText(map.get(THIRD_COLUMN));
        txtFourth.setText(map.get(FOURTH_COLUMN));
    txtFifth.setText(map.get(FIFTH_COLUMN));
        txtSixth.setText(map.get(SIXTH_COLUMN));

        return convertView;
    }

    public void clear() {
        list.clear();
        this.notifyDataSetChanged();
    }

}

而且,这是填充列表的代码部分。

private void showInboxMessages() {
        String SORT_ORDER = "date DESC";
        Uri uriSms = Uri.parse("content://sms/inbox");
        Cursor cursor = this.getContentResolver().query(uriSms, null, null, null, SORT_ORDER);
        if (cursor != null) {
            cursor.moveToLast();
            if (cursor.getCount() > 0) {    
                HashMap<String, String> contacts = new HashMap<String, String>();
                int _id = 1;
                do {
                    //String _id = cursor.getString(cursor.getColumnIndex("_id"));
                    String person = cursor.getString(cursor.getColumnIndex("person"));
                    String address = cursor.getString(cursor.getColumnIndex("address"));

                    if (person == null || person.equals("")) {
                        if (contacts.containsKey(address))
                            person = (String) contacts.get(address);
                        else {
                            person = Methods.getContactName(this, address);
                            contacts.put(address,person);
                        }
                    } 
                    String body = cursor.getString(cursor.getColumnIndex("body"));
                    Long date = cursor.getLong(cursor.getColumnIndex("date"));
                    Date dateVal=new Date(date);
                    SimpleDateFormat dateFormat = new SimpleDateFormat(Constants.DATE_FORMAT2, Locale.getDefault());
                    String datetext = dateFormat.format(dateVal);
                    add_to_list(String.valueOf(_id), "", person, address, datetext, body);
                    _id ++;
                } while (cursor.moveToPrevious());
            }
        }
    }


private void add_to_list(String i, String n, String c, String d, String e, String f) {
        HashMap<String, String> temp = new HashMap<String, String>();
        temp.put(FIRST_COLUMN, i);
        temp.put(SECOND_COLUMN, n);
        temp.put(THIRD_COLUMN, c);
        temp.put(FOURTH_COLUMN, d);
        temp.put(FIFTH_COLUMN, e);
        temp.put(SIXTH_COLUMN, f);
        listarray.add(temp);
        adapter.notifyDataSetChanged();

    }

尝试从 add_to_list 方法中删除 adapter.notifyDataSetChanged(); 并在 if (cursor.getCount() > 0) 中添加此行,但是 after/outside 执行 While 循环。

//Copy and paste code below then see if there is change. This must be work for now. Hope this help. Setting final to all view/position to not change the value.


import java.util.*;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class ListViewAdapter extends BaseAdapter {

private String FIRST_COLUMN = "First";
private String SECOND_COLUMN = "Second";
private String THIRD_COLUMN = "Third";
private String FOURTH_COLUMN = "Fourth";
private String FIFTH_COLUMN = "Fifth";
private String SIXTH_COLUMN = "Sixth";
String class_name="";

public ArrayList<HashMap<String, String>> list;
Activity activity;
TextView txtFirst;
TextView txtSecond;
TextView txtThird;
TextView txtFourth;
TextView txtFifth;
TextView txtSixth;

public ListViewAdapter(Activity activity,
                       ArrayList<HashMap<String, String>> list) {
    super();
    this.activity = activity;
    this.list = list;
    class_name = activity.getClass().toString();

}

@Override
public int getCount() {

    return list.size();
}

@Override
public Object getItem(int position) {
    return list.get(position);
}

@Override
public long getItemId(int position) {
    return 0;
}

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

    final LayoutInflater inflater = activity.getLayoutInflater();
    if (convertView == null) {  
            convertView = inflater.inflate(R.layout.messages_row, null);
            txtFirst = (TextView) convertView.findViewById(R.id.tvMsgId_msg);
            txtSecond = (TextView) convertView.findViewById(R.id.tvCtId_msg);
            txtThird = (TextView) convertView.findViewById(R.id.tvCtName_msg);
            txtFourth = (TextView) convertView.findViewById(R.id.tvCtNo_msg);
            txtFifth = (TextView) convertView.findViewById(R.id.tvMsgDate_msg);
            txtSixth = (TextView) convertView.findViewById(R.id.tvSms_msg);
    }

    HashMap<String, String> map = list.get(position);
    txtFirst.setText(map.get(FIRST_COLUMN));
    txtSecond.setText(map.get(SECOND_COLUMN));
    txtThird.setText(map.get(THIRD_COLUMN));
    txtFourth.setText(map.get(FOURTH_COLUMN));
txtFifth.setText(map.get(FIFTH_COLUMN));
    txtSixth.setText(map.get(SIXTH_COLUMN));

    return convertView;
}

public void clear() {
    list.clear();
    this.notifyDataSetChanged();
}

}

基本上列表视图会回收您的视图。您需要检查 viewholders 的概念。 例如:

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

    ViewHolder holder;

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.list_entry, null);
        holder = new ViewHolder();
        holder.nameTextView = (TextView) convertView.findViewById(R.id.person_name);
        holder.surnameTextView = (TextView) convertView.findViewById(R.id.person_surname);
        holder.personImageView = (ImageView) convertView.findViewById(R.id.person_image);
        convertView.setTag(holder);
    }
    else {
        holder = (ViewHolder) convertView.getTag();
    }

    Person person = getItem(position);

    holder.nameTextView.setText(person.getName());
    holder.surnameTextView.setText(person.getSurname());
    //holder.personImageView.setImageBitmap(person.getImage());

    return convertView;
}

我已经更改了适配器的代码 class 并将 ArrayList 与我的数据模型一起使用 class 'Message'。现在列表可以正常显示和滚动了。

import java.util.ArrayList;    
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class CustomAdapter extends ArrayAdapter<Message> {
    private ArrayList<Message> dataItems;
    Context context;

    public CustomAdapter(Context context, ArrayList<Message> items) {
        super(context, R.layout.messages_row, items);
        this.context = context;
        this.dataItems = items;
    }

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

        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        convertView = inflater.inflate(R.layout.messages_row, parent, false);

        TextView _id = (TextView) convertView.findViewById(R.id.tvMsgId_msg);
        TextView ctId = (TextView) convertView.findViewById(R.id.tvCtId_msg);
        TextView ctName = (TextView) convertView.findViewById(R.id.tvCtName_msg);
        TextView ctNo = (TextView) convertView.findViewById(R.id.tvCtNo_msg);
        TextView msgDate = (TextView) convertView.findViewById(R.id.tvMsgDate_msg);
        TextView msg = (TextView) convertView.findViewById(R.id.tvSms_msg);

        Message obj = (Message) dataItems.get(position);

        _id.setText(String.valueOf(obj.get_id()));
        ctId.setText(String.valueOf(obj.getContact_id()));
        ctName.setText(String.valueOf(obj.getContact_Name()));
        ctNo.setText(String.valueOf(obj.getContact_No()));
        msgDate.setText(String.valueOf(obj.getSms_date()));
        msg.setText(String.valueOf(obj.getSms()));


        return convertView;
    }
}