Mirko Benedetti Mirko Benedetti - 1 year ago 90
Java Question

Populate dynamically expandablelistview, after expansion of group

I have a problem with an expandablelistview, I have implemented a simple BaseExpandableListAdapter adapter for it, as many on-line tutorials tell to do.

When I populate the expandablelistview groups and childs at the same time, at the beginning of a fragment, I have no problem, but when I try to populate childs when they are expanded (inside an onGroupClick) I get a NullPointerException at this point of the adapter implementation:

public int getChildrenCount(int groupPosition) {
return namesCollections.get(contactNames.get(groupPosition)).size();

I other words namesCollections which I initialize in the constructor of the adapter (below), appear to be null:

public FavoriteAdapter(Activity context, List<String> contactNames,
Map<String, List<String>> namesCollections) {
this.context = context;
this.namesCollections = namesCollections;
this.contactNames = contactNames;

How can I populate childs on expansion of the groups?

Answer Source

If you're trying to add the backing data after the click, that means this collection you are trying to get the size of is either null or zero. Most likley null, since this is where you are getting your null pointer at. You can't call .size() on a null reference.

public int getChildrenCount(int groupPosition) {
    return namesCollections.get(contactNames.get(groupPosition)).size();

Since the collection is empty at this point, and you plan to add the data later, you need to either initialize the collection and fill it with dummy items (which you replace when you get your data), or not use the collection size for determining how many children are in the collection, since it's not an accurate measure.

Also make sure to call notifyDataSetHasChanged() when you add your backing data, so the views are rebuilt.

On your performance question: The ExpandableListView doesn't create views for children (and thus doesn't query data for them) until that group is expanded, and listview is scrolled such that the the child would be displayed on the screen. Now you still have to pay the performance penalty for having a complete set of backing data if you fetch all the data at the start, instead of dynamically. So there is reason to fetch the data dynamically, but the ELV isn't wasting any time querying that backing data or building views for children it doesn't yet have to display.