Android-адаптер ListView не обновляется

У меня возникли проблемы с обновлением списка с помощью адаптера. Я искал онлайн в течение последнего часа, и я не могу найти решение, которое позволит обновить список.

Я пробовал notifyDataSetChanged, а также listView.invalidate, но ничего не работает. Любая помощь будет принята с благодарностью. Я могу видеть, что данные обновляются с помощью logcat, но он не обновляется на экране, и я понятия не имею, почему.

Ниже приведен код.

ArrayList<Student> students = new ArrayList<Student>(); listview = (ListView) findViewById(R.id.listView); adapter = new StudentAdapter(this, R.layout.listitemlayout, students); listview.setAdapter(adapter); 

Пользовательский адаптер

 public class StudentAdapter extends ArrayAdapter<Student>{ Context context; int layoutResourceId; ArrayList<Student> data = null; public StudentAdapter(Context context, int layoutResourceId, ArrayList<Student> data) { super(context, layoutResourceId, data); this.layoutResourceId = layoutResourceId; this.context = context; this.data = data; } public void updateStudentsList(ArrayList<Student> newlist){ data.clear(); data = newlist; this.notifyDataSetChanged(); } public void updateStudentTime(){ for (Student s : data) { s.updateElapsedTime(); } this.notifyDataSetChanged(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if(row == null){ LayoutInflater inflater = ((Activity)context).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); Student student = data.get(position); TextView title = (TextView)row.findViewById(R.id.txtTitle); title.setText(student.getFirstname() + " " + student.getLastname()); TextView subTitle = (TextView)row.findViewById(R.id.txtSubTitle); subTitle.setText(student.getStudentID()); TextView duration = (TextView)row.findViewById(R.id.textDuration); duration.setText(student.getElapsedTime()); } return row; } } 

Я часто обновляю данные с помощью потока.

 Runnable runnable = new Runnable() { public void run() { runOnUiThread(new Runnable() { public void run() { // Updates how long the student is in the centre. adapter.updateStudentTime(); adapter.notifyDataSetChanged(); listview.invalidate(); Log.i("Debug", "Running on UI Thread"); } }); handler.postDelayed(this, 1000); } }; handler.postDelayed(runnable, 1000); 

ListView переработает представление, поэтому вы должны установить данные в getView. И i f(row == null){ означает, что данные не будут обновляться, используйте только старые данные.

Вы должны сделать вот так:

 Class ViewHolder { TextView title; TextView subTitle; TextView duration; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; ViewHolder holder = null; if(row == null){ LayoutInflater inflater = ((Activity)context).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); Student student = data.get(position); holder = new ViewHolder(); holder.title = (TextView)row.findViewById(R.id.txtTitle); holder.subTitle = (TextView)row.findViewById(R.id.txtSubTitle); holder.duration = (TextView)row.findViewById(R.id.textDuration); row.setTag(holder); } else { holder = row.getTag(); } holder.title.setText(student.getFirstname() + " " + student.getLastname()); holder.subTitle.setText(student.getStudentID()); holder.duration.setText(student.getElapsedTime()); return row; } 

Подумайте, что приведенный ниже код не позволяет обновить список.

 if(row == null){ ... } 

В коде сказано, что при обновлении списка. Будет проверяться, что строка имеет значение NULL (означает, что отображение строки на экране создается или нет). Когда вы обновляете список, строка уже создана. Так что это НЕ NULL, новые данные не будут установлены!

Вы должны изменить что-то вроде этого:

 public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if(row == null){ LayoutInflater inflater = ((Activity)context).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); } Student student = data.get(position); ... }