ListView with a custom adapter, adding elements one by one

tweetysat picture tweetysat · Feb 23, 2012 · Viewed 23.6k times · Source

Reading this question, I tried the example given in the answer and it's working fine. Now I want to do the same but with a custom adapter using a Student class. So I have:

public class AsyncDemo extends ListActivity {
  private static final String[] items={"lorem", "ipsum", "dolor",
                                      "sit", "amet", "consectetuer",
                                      "adipiscing", "elit", "morbi",
                                      "vel", "ligula", "vitae",
                                      "arcu", "aliquet", "mollis",
                                      "etiam", "vel", "erat",
                                      "placerat", "ante",
                                      "porttitor", "sodales",
                                      "pellentesque", "augue",
                                      "purus"};
    private List<Student>  students;
    private StudentAdapter studentsAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

//    setListAdapter(new ArrayAdapter<String>(this,
//                        android.R.layout.simple_list_item_1,
//                        new ArrayList<String>()));

    students = new ArrayList<Student>();
    students.clear();
    studentsAdapter = new StudentAdapter(this, students);
    setListAdapter(studentsAdapter);

    new AddStringTask().execute();
    }

//  class AddStringTask extends AsyncTask<Void, String, Void>
    class AddStringTask extends AsyncTask<Void, Student, Void>
    {
    @Override
    protected Void doInBackground(Void... unused)
    {
      for (String item : items)
      {
        Student student = new Student();
        student.setName(item);
        publishProgress(student);

//        publishProgress(item);

        SystemClock.sleep(200);
  }

  return(null);
}

//    @SuppressWarnings("unchecked")
//    @Override
//    protected void onProgressUpdate(String... item) {
//      ((ArrayAdapter<String>)getListAdapter()).add(item[0]);
//    }
    @Override
    protected void onProgressUpdate(Student... student)
    {
      ((StudentAdapter)getListAdapter()).add(student[0]);
    }

    @Override
    protected void onPostExecute(Void unused) {
      Toast
        .makeText(AsyncDemo.this, "Done!", Toast.LENGTH_SHORT)
        .show();
    }
  }
}


package com.commonsware.android.async;

public class Student
{
private String name;

public void setName(String name) 
  {
  this.name = name;
  }
public String getName() 
  {
  return name;
  }
}

and:

public class StudentAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    private List<Student> students;
    private ViewHolder holder;

    public StudentAdapter(Activity context,List<Student> students)
    {
        this.inflater = LayoutInflater.from(context);
        this.students = students;
    }

public void add(Student album)
{
    Log.w("StudentAdapter","add");
    students.add(album);
}

@Override
public int getCount()
{
    Log.w("StudentAdapter","getCount : " + students.size());
    return students.size();
}

@Override
public Object getItem(int position)
{
    Log.w("StudentAdapter","getItem");
    return students.get(position);
}

@Override
public long getItemId(int position)
{
    Log.w("StudentAdapter","getItemId");
    return position;
}

private class ViewHolder
{
    TextView  tv_album_name;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    Log.w("StudentAdapter","getView");
    View rowView = convertView;

    if(rowView == null)
    {
        rowView = inflater.inflate(R.layout.student_item,null);
        holder = new ViewHolder();
        holder.tv_album_name = (TextView) rowView.findViewById(R.id.tv_student_name);
        rowView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) rowView.getTag();
    }

    holder.tv_album_name.setText(students.get(position).getName());

    return rowView;
}

}

The problem is that only first row is displayed and the Toast after a few seconds. I don't understand why(in the log) there is only one call to getView! Is there an error on my code? Something missing? Can someone help me?

Answer

user picture user · Feb 23, 2012

Also call notifyDataSetChanged() in your add() method from the Adapter:

public void add(Student album)
{
    Log.w("StudentAdapter","add");
    students.add(album);
    notifyDataSetChanged();
}