Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ListView adapter wont refresh

I'm having a lot of trouble refreshing a list view with a custom adapter. I've been searching online for the past hour and I can't seem to find any solution that will make my list view refresh.

I've tried notifyDataSetChanged, and also listView.invalidate, but nothing seems to be working. Any help would be greatly appreciated. I can see the data being updated using logcat, but it is not being refreshed on the screen and I have no idea why.

Below is the code.

ArrayList<Student> students = new ArrayList<Student>();

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

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

I update the data using a thread every so often.

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);
like image 445
SikhWarrior Avatar asked May 02 '13 03:05

SikhWarrior


1 Answers

ListView will recycle the view, so you must set data in getView. and if(row == null){ means that data will not refresh, only use the old data.

you should do like this:

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;
}
like image 176
buptcoder Avatar answered Nov 08 '22 16:11

buptcoder