I have a custom adapter that uses an onclickListener to change the parent text, I can't figure out how to get the notifyDataSetChanged method to work within the adapter.
what should happen is I have an expandable view, and when you click on the button that is within the child it updates the parent with the text of the child...
Here's a picture example of what SHOULD happen. before clicking button USE THIS:
and After clicking button USE THIS:
"Choose an Ingredient" changes to "Rice, cups" or whatever is clicked on
so in my code shown, after clicking the button it should update parent, which it does, then refresh the view which I can't do for some reason?
heres my code, Thanks in advance!
package com.example.andrew.mypantry;
import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.HashMap;
import java.util.List;
/**
* Created by andrew on 7/1/2015.
*/
public class IngExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader; //header titles
//child data in format of <header title, child title>
private HashMap<String, List<String>> listDataChild;
public IngExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listDataChild) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listDataChild;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
private void test() {
//notifyDataSetChanged();
//super.notifyDataSetChanged();
//this.notifyDataSetChanged();
}
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition,childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.ingredient_list_item, null);
}
TextView txtListChild = (TextView) convertView.findViewById(R.id.ingredientContentTextView);
txtListChild.setText(childText);
//handle button
Button ingredientButton = (Button)convertView.findViewById(R.id.useIngredient_button);
ingredientButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//change header to ingredient selected
listDataHeader.set(groupPosition, childText);
//test();
}
});
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPostion) {
return this.listDataHeader.get(groupPostion);
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if(convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.ingredient_list_group, null);
}
//handle textView
final TextView listHeader = (TextView) convertView.findViewById(R.id.ingredientGroupTextView);
listHeader.setTypeface(null, Typeface.BOLD);
listHeader.setText(headerTitle);
//handle button
Button deleteButton = (Button)convertView.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//remove item from list
Log.d("TESTING", "item should be removed");
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
As beworker mentioned, your problem comes from using wrong data structure and here is why your app crashes. You are using header titles as keys to your hashmap and when you modify a title in listDataHeader
the modification is correctly applies to it but not to the key object inside the hashmap. Meaning that your children still exist under the old title key inside the hashmap and the new title key has null
as its value. Thus you will get a NullPointerException
when you call the
this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
since
this.listDataChild.get(this.listDataHeader.get(groupPosition))
returns Null
Solution would be using ArrayList for header titles and ArrayList> for children. The key in both of these arrayLists is your group index.
I believe the issue is in the data structures you use. You keep list of children assigned to the parent's name in a hash table. When parent's name changes in the list of parents, old children assignment in the hash table is not valid anymore.
I would suggest you to use SparseArray<List<String>>
or List<List<String>>
for listDataChild
field. It will map group position to the list of children directly. Thus changing parent's name in listDataHeader
wont break data consistency, as the group position will stay the same. Now you should be able to safely use notifyDataSetChanged()
method to update headers.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With