Question

I have a class ShoppingList with the following Map:

@DatabaseField(dataType = DataType.SERIALIZABLE)
Map<Category, List<Product>> products;

Then, on a Fragment, I have a ListView that should show all Categories. Therefore, I set the Adapter for it with the following code:

aisles.setAdapter(new ShoppingListEditAdapter(getActivity(), new ArrayList<Category>(mShoppingList.getMap().keySet())));

By default it should be empty. If I click a button, a Dialog opens, and there I input the text for the new category or aisle that I want to create. Thus, I run the following code:

Category category = new Category();
category.setName(editText.getText().toString());
mShoppingList.getMap().put(category, new ArrayList<Product>());
try {
    helper.getShoppingListDao().update(mShoppingList);
    ((BaseAdapter) aisles.getAdapter()).notifyDataSetChanged();
} catch (SQLException e) {
    e.printStackTrace();
}

This should modify the ShoppingList I have for this Fragment, adding a Category to the Map. However, even if I call notifyDatasetChanged() for my Adapter or restart the application, the ListView doesn't get populated with the data. Both Category and Product are Serializable. Why doesn't it get populated?

Was it helpful?

Solution

In keeping with what I've posted as a comment, here is a simple adapter that will accept a Map and display the keys of the map as the values of the list. I've not tested it in accordance with the actual item id's, but for displaying a map that will be mutated, it seems to work (i.e. if the map itself is changed and notifyDataSetChanged() is called, it will work). I've counted on ArrayAdapter to do the heavy lifting and just overrode the methods I wanted.

The obvious downside is I'm not sure how expensive it is to call keySet().toArray() but I imagine it's a linear time operation, beyond the extra memory usage. But basically I don't know a great way to get around this issue, as it relies on taking a Set into some sort of ordered collection.

    public class MapAdapter<K, V> extends ArrayAdapter<K> {

    private Map<K, V> items;

    public MapAdapter(Context context, int resource, Map<K,V> items) {
        super(context, resource);
        this.items = items;
    }

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

    @Override
    public K getItem(int position) {
        return ((K []) items.keySet().toArray())[position];
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top