Thursday, August 15, 2013

Custom BaseAdapter and notifyDataSetChanged

When making a custom adapter from BaseAdapter, I got the problem that calling notifyDataSetChanged() doesn't work - new data isn't refreshed as expected.

Below is my code:

 public class RowAdapter extends BaseAdapter {  
   private List<? extends RowDO> data;  
   public RowAdapter(List<? extends RowDO> d) {  
     data = d;  
   }  
   @Override  
   public int getCount() {  
     return data.size();  
   }  
   ...  
 }  
 public class MainActivity extends Activity {  
   private RowAdapter rowAdapter;  
   private List<RowDO> listDO;  
   ...  
   private void displayList(){  
     listDO = getListDO();  
     if (rowAdapter == null) {  
       rowAdapter = new RowAdapter(listDO);  
       ListView listView = (ListView) findViewById(R.id.list);  
       listView.setAdapter(rowAdapter);  
     } else {  
       rowAdapter.notifyDataSetChanged();  
     }  
   }  
   private List<RowDO> getListDO() {  
     List<RowDO> list = new ArrayList<RowDO>();  
     list.add(new RowDO());  
     if (some_conditions) {  
       ...  
     }  
     return list;  
   }  
 }  

After google around, I found Snicolas answer

The list I use in my adapter (data) is a reference to the list created in getListDO() when passing it to adapter at first time. So the next time, when I re-assign the listDO with the new list, the old copy in the adapter is still there.

To correct this, we should keep the original list as below code:

 private List<RowDO> listDO = new ArrayList<RowDO>();  
 private void displayList(){  
   listDO.clear();  
   listDO.addAll(getListDO());  
   if (rowAdapter == null) {   
     rowAdapter = new RowAdapter(listDO);   
     ListView listView = (ListView) findViewById(R.id.list);   
     listView.setAdapter(rowAdapter);   
    } else {   
     rowAdapter.notifyDataSetChanged();   
    }   
 }  

11 comments:

  1. Hello Luan Nguyen ,
    can u please help me out how to use adapter.notifyDataSetChanged(); method
    for my example like similar sample code please.

    public class MainActivity extends Activity {
    ListView lv_names;
    String[] names = { "a", "b", "c", "d", "e",
    "e", "f", "a", "b", "c", "d", "e",
    "e", "f", "a", "b", "c", "d", "e",
    "e", "f".........};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main_h);
    LoadUiComponents();

    // adapter = new ArrayAdapter(this, R.layout.cust_text,
    // males);
    // TextView tv = (TextView) findViewById(R.id.textView1);


    lv_names.setAdapter(new namesAdapter(getApplicationContext()));

    lv_names.setCacheColorHint(0);

    }

    public class namesAdapter extends BaseAdapter {
    Context mContext;
    LayoutInflater inflater;

    public namesAdapter(Context context) {
    inflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    if (convertView == null) {
    convertView = inflater.inflate(R.layout.cust_text, null);
    }

    TextView tv = (TextView) convertView.findViewById(R.id.textView1);


    tv.setText("" + names[position]);

    return convertView;
    }

    @Override
    public int getCount() {
    // TODO Auto-generated method stub

    return names .length;
    }

    @Override
    public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
    }

    @Override
    public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
    }

    }

    may be this is sample code i want to use notifySetDataChanged(); for this please help me out

    ReplyDelete
  2. Hi Sravan,

    What's problem with your code?

    Below is my simple worked example.

    Luan Nguyen

    public class HelloAndroid extends Activity {
    private NamesAdapter rowAdapter;
    List names = new ArrayList();

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    names.clear();
    names.addAll(getNames());
    if (rowAdapter == null) {
    rowAdapter = new NamesAdapter(getApplicationContext(),names);
    ListView listView = (ListView) findViewById(R.id.list);

    listView.setAdapter(rowAdapter);
    } else {
    rowAdapter.notifyDataSetChanged();
    }
    }

    private List getNames() {
    List list = new ArrayList();
    list.add("Luan Nguyen");
    list.add("Sravan shetty");
    return list;
    }
    }

    public class NamesAdapter extends BaseAdapter {
    Context mContext;
    LayoutInflater inflater;
    List names;

    public NamesAdapter(Context context,List names) {
    inflater = LayoutInflater.from(context);
    this.names = names;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    if (convertView == null) {
    convertView = inflater.inflate(R.layout.row_view, null);
    }

    TextView tv = (TextView) convertView.findViewById(R.id.textView1);

    tv.setText("" + names.get(position));

    return convertView;
    }

    @Override
    public int getCount() {
    // TODO Auto-generated method stub

    return names.size();
    }

    @Override
    public Object getItem(int position) {
    // TODO Auto-generated method stub
    return names.get(position);
    }

    @Override
    public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
    }

    }

    ReplyDelete
  3. Hiii....Luan Nguyen
    Nice Article but Plz help me...
    I want to Refresh listView After Deleting....
    like I have one listView and when we click on listView item than one Alert Dialog will be Open with 2 buttons.[Update & Delete].
    but when i Click on Delete button data(listView item) will be Delete but listView not Refresh.Than tell me where i put notifyDataSetChanged()..

    ReplyDelete
  4. also i m Performing Updating & Deleting using Sqlitedatabase.
    but i dont no where i put listView Refresh method.

    in myCustomAdapter...in my ListviewActivity...????

    ReplyDelete
  5. Sagar, could you give me your code?

    ReplyDelete
    Replies
    1. My all Code is properly working like even delete.....but problem was listView not give any response after deleting the data...even my data is delete...After reOpening that listView Activity i found my data was deleted...but not that time when i pressed my Button.

      Delete
  6. And Finally i m Sending my ListViewMainActivity code....in which i want to Refresh my listView After pressing Delete Button of My Alert dialog....see i already used notifyDataSetChanged(); for Refresh in my listView OnItemClick(). but it didn't work.

    ReplyDelete
  7. ok sir i sent my code as u say....now when you will be free tell me...if u find solution of my problem...Thank u in Advance.

    ReplyDelete
  8. Sir i cant find my code in your blog....it properly uploaded i had seen...where that was gone...???

    ReplyDelete
    Replies
    1. Hi Sagar,
      why don't you zip just them and share via Google drive or Dropbox? or just push them to github

      Delete