2

I used list adapter with map values as data. When I use adapter.notifyDataSetChanged(); the data in the list not updating. But if I replace the Map with ArrayList everything working fine. Following is my adapter code.

public class CategoryAdapter extends BaseAdapter {
ArrayList<Category> list = new ArrayList<Category>();
Context context;

public CategoryAdapter(Context context, Map<String, Category> categories) {
    this.context = context;
    list.clear();
    list.addAll(categories.values());
}

@Override
    public int getCount() {
        return list.size();
    }

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

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.category_list_item, null);
            handler = new ViewHandler();
            handler.name = (TextView) convertView.findViewById(R.id.name);
            handler.count = (TextView) convertView.findViewById(R.id.count);
            convertView.setTag(handler);
        } else {
            handler = (ViewHandler) convertView.getTag();
        }
        Category category = list.get(position);
        handler.name.setText(category.getMenuName());
        handler.count.setText(category.getCount() + "");
        if (category.getCount() <= 0) {
            handler.count.setVisibility(View.INVISIBLE);
        } else {
            handler.count.setVisibility(View.VISIBLE);
        }

        return convertView;
    }
}

and my activity code is

private void loadCategories() {
    sampleDB = openOrCreateDatabase(AppConstants.DB_NAME, MODE_PRIVATE,
            null);
    Cursor menuCursor = sampleDB.rawQuery("select * from menu", null);

    categories.clear();
    while (menuCursor.moveToNext()) {
        String menu = menuCursor.getString(menuCursor
                .getColumnIndex("name"));
        String id = menuCursor.getString(menuCursor.getColumnIndex("id"));
        Category category = new Category(menu, id);
        categories.put(id, category);
    }
    menuCursor.close();
    categoryAdapter.notifyDataSetChanged();
}

in oncreate() method I have declared adapter as follows

categoryAdapter = new CategoryAdapter(context, categories);
        categoryList.setAdapter(categoryAdapter);
        loadCategories();

Every time I click on refresh button it calls loadCategories(); method. In the same code if I replace Map with ArrayList everything working fine.

Now My question is why List is not refreshing with Map values. Please give me clarification regarding this.

Thanks in advance.

Krish4906
  • 121
  • 1
  • 1
  • 9
  • Where are you adding/changing the contents of the `categoryAdapter` – 0xDEADC0DE Jun 27 '14 at 14:09
  • Sorry. `categoryAdapter` is declared using `categories` Map. See my updated Question. Everytime I click on refresh button loadCategories() will called. and with in that categories values changes. – Krish4906 Jun 27 '14 at 14:14
  • is `onCreate()` the only place where you create an instance of `CategoryAdapter`?. If so, the `ArrayList list` of your `categoryAdapter` doesn't not get updated – 0xDEADC0DE Jun 27 '14 at 14:18
  • yes, `oncreate()` is the only place for creating inastance for `CategoryAdapter`. `ArrayList list` doesn't gets effected even if I use `notifyDataSetChanged()`. – Krish4906 Jun 27 '14 at 14:24
  • That is because you don't update the list of the adapter instance. Let me work out an answer which I think work. A little moment please... – 0xDEADC0DE Jun 27 '14 at 14:27
  • I posted an answer. This should solve your problem – 0xDEADC0DE Jun 27 '14 at 14:35

2 Answers2

5

You must add a method to your CategoryAdapter to change the instance's list, like so

public class CategoryAdapter extends BaseAdapter {
ArrayList<Category> list = new ArrayList<Category>();
Context context;

public CategoryAdapter(Context context, Map<String, Category> categories) {
    this.context = context;
    list.clear();
    list.addAll(categories.values());
}

@Override
public int getCount() {
    return list.size();
}

//ADD THIS METHOD TO CHANGE YOUR LIST
public void addItems(Map<String, Category> categories){
    list.clear();
    list.addAll(categories.values());
}

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

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.category_list_item, null);
        handler = new ViewHandler();
        handler.name = (TextView) convertView.findViewById(R.id.name);
        handler.count = (TextView) convertView.findViewById(R.id.count);
        convertView.setTag(handler);
    } else {
        handler = (ViewHandler) convertView.getTag();
    }
    Category category = list.get(position);
    handler.name.setText(category.getMenuName());
    handler.count.setText(category.getCount() + "");
    if (category.getCount() <= 0) {
        handler.count.setVisibility(View.INVISIBLE);
    } else {
        handler.count.setVisibility(View.VISIBLE);
    }

    return convertView;
}
}

and change your loadCategories like so (note that I call the addItems() before notifyDataSetChanged()

private void loadCategories() {
sampleDB = openOrCreateDatabase(AppConstants.DB_NAME, MODE_PRIVATE,
        null);
Cursor menuCursor = sampleDB.rawQuery("select * from menu", null);

categories.clear();
while (menuCursor.moveToNext()) {
    String menu = menuCursor.getString(menuCursor
            .getColumnIndex("name"));
    String id = menuCursor.getString(menuCursor.getColumnIndex("id"));
    Category category = new Category(menu, id);
    categories.put(id, category);
}
menuCursor.close();

//ADD CALL TO addItems TO UPDATE THE LIST OF THE categoryAdapter instance
categoryAdapter.addItems(categories);
categoryAdapter.notifyDataSetChanged();
}
0xDEADC0DE
  • 2,453
  • 1
  • 17
  • 22
  • without using `addItems()` if I repalce constructor with `public CategoryAdapter(Context context, ArrayList categories) { this.context = context; list=categories; }` it is working fine, but not with Map. Can you please explain me. – Krish4906 Jun 27 '14 at 14:48
  • Do you call that constructor in `loadCategories()` ? – 0xDEADC0DE Jun 29 '14 at 13:05
  • no. after updating of categories ArrayList, I have called notifyDataSetChanged() and it is working fine. – Krish4906 Jun 30 '14 at 06:51
  • Oh I see now. In your constructor, you assign `categories` to `list`. So if you update your `categories`, you update your `list` and then your data has changed – 0xDEADC0DE Jun 30 '14 at 08:08
  • Now I understood. Thank you for replay. – Krish4906 Jun 30 '14 at 08:11
2

have you tried saying:

categoryList.setAdapter(null);
categoryList.setAdapter(categoryAdapter);
erik
  • 4,946
  • 13
  • 70
  • 120