John Joe
John Joe

Reputation: 12803

NullPointerException at ExpandableListAdapter.getChild()

Been stucked at here more than a week but still unable to solve! I have an expandable listView where the data were retrieved from SQLite and set to expListAdapter. Once the arrow clicked, it will display two child items.

AddMonthlyExpenses

public class AddMonthlyExpenses extends AppCompatActivity {

    ArrayList<ListObj> groupList= new ArrayList<ListObj>();;
    List<String> childList;
    Map<ListObj, List<String>> laptopCollection;
    ExpandableListView listview;
    ExpandableListAdapter expListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_monthly_expenses);
        laptopCollection = new LinkedHashMap<ListObj, List<String>>();
        listview = (ExpandableListView) findViewById(R.id.exlistView);
        expListAdapter = new ExpandableListAdapter(getApplication(), groupList, laptopCollection);
        listview.setAdapter(expListAdapter);
        retrieveList(name);
    }

 public void retrieveList(String name) {
        database = mdb.getReadableDatabase();
        Cursor cursor = database.rawQuery("SELECT * FROM " + MyDatabaseHelper.TABLE__TASK + " WHERE Name = ? ", new String[]{name}, null);
        if (cursor != null && cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                groupList = new ArrayList<ListObj>();
                int iD = cursor.getInt(cursor.getColumnIndex("ID"));
                String month = cursor.getString(cursor.getColumnIndex("Month"));
                double budget = cursor.getDouble(cursor.getColumnIndex("Budget"));
                groupList.add(new ListObj(iD,month,budget));
                if (expListAdapter != null) {
                    expListAdapter.add(iD, month, budget);
                    createCollection();  // for child items
                    listview.setAdapter(expListAdapter);
                }
            }
        }
    }

 private void createCollection() {
        String[] options = {"Edit","Delete"};
        for (ListObj laptop : groupList) {
            loadChild(options);
            laptopCollection.put(laptop, childList);
        }
    }

    private void loadChild(String[] laptopModels) {
        childList = new ArrayList<String>();
        for (String model : laptopModels)
            childList.add(model);
    }
}

ExpandableListAdapter

  public class ExpandableListAdapter extends BaseExpandableListAdapter {

    private Context context;
    Map<ListObj, List<String>> laptopCollections;
    private ArrayList<ListObj> laptops;
    double used = 0;
    private LayoutInflater mInflater;

    public ExpandableListAdapter(Context context, ArrayList<ListObj> laptops, Map<ListObj, List<String>> laptopCollections) {
        this.context = context;
        this.laptopCollections = laptopCollections;
        this.laptops = laptops;
        mInflater = LayoutInflater.from(context);
    }

    public Object getChild(int groupPosition, int childPosition) {  // error line
        if (laptopCollections.get(laptops.get(groupPosition)).get(childPosition) != null && !laptopCollections.get(laptops.get(groupPosition)).get(childPosition).isEmpty()) {
            return laptopCollections.get(laptops.get(groupPosition)).get(childPosition);
        }
        return 1;
    }

    public void add(int id, String month, double budget) {
        String[] splited = month.split("\\s+");
        ListObj obj = new ListObj(id, month, budget);
        obj.setYear(splited[1]);
        obj.setMonth(splited[0]);
        obj.setBudget(budget);
        obj.setID(id);
        laptops.add(obj);
        this.notifyDataSetChanged();
    }

    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    public int getCount() {
        return laptops.size();
    }

    public ListObj getItem(int position) {
        return laptops.get(position);
    }

    public View getChildView(final int groupPosition, final int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final String laptop = (String) getChild(groupPosition, childPosition);   // here the error line 
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.child_item, null);
        }
        TextView edit = (TextView) convertView.findViewById(R.id.textEdit);
        edit.setText(laptop);
        return convertView;
    }

    public int getChildrenCount(int groupPosition) {
        if (laptopCollections.get(laptops.get(groupPosition)) != null && !  laptopCollections.get(laptops.get(groupPosition)).isEmpty()) {
            return  laptopCollections.get(laptops.get(groupPosition)).size();
        }
        return 1;
    }

    public Object getGroup(int groupPosition) {
        return laptops.get(groupPosition);
    }

    public int getGroupCount() {
        return this.laptops.size();
    }

    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        ExpensesAdapter.ViewHolder holder = null;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.expenses_adapter, null);
            holder = new ExpensesAdapter.ViewHolder();
            holder.month = (TextView) convertView.findViewById(R.id.textMonth);
            holder.budget = (TextView) convertView.findViewById(R.id.textAmount);
            holder.year = (TextView) convertView.findViewById(R.id.textYear);
            convertView.setTag(holder);
        } else {
            holder = (ExpensesAdapter.ViewHolder) convertView.getTag();
        }
        holder.month.setText(laptops.get(groupPosition).getMonth());
        holder.budget.setText(String.format("%.2f", laptops.get(groupPosition).getBudget()));
        holder.year.setText(laptops.get(groupPosition).getYear());
        return convertView;
    }

    public boolean hasStableIds() {
        return true;
    }

    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}

Error

10-26 00:03:57.114 23612-23612/com.example.tony.monthlyexpenses E/AndroidRuntime: FATAL EXCEPTION: main java.lang.NullPointerException at com.example.tony.monthlyexpenses.adapter.ExpandableListAdapter.getChild(ExpandableListAdapter.java:42) at com.example.tony.monthlyexpenses.adapter.ExpandableListAdapter.getChildView(ExpandableListAdapter.java:87) at android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:451) at android.widget.AbsListView.obtainView(AbsListView.java:2232) at android.widget.ListView.makeAndAddView(ListView.java:1849) at android.widget.ListView.fillDown(ListView.java:678) at android.widget.ListView.fillSpecific(ListView.java:1339)

My apps screen shot

enter image description here

I tried debug but nothing is null !

enter image description here

You can clone my project from link below

https://github.com/wseng92/MonthlyExpenses

Upvotes: 4

Views: 632

Answers (3)

pirho
pirho

Reputation: 12285

I ran in to a similar problem year or two ago. Can not remember anymore which version it was.

Starting from call

public Object getChild(int groupPosition, int childPosition) {
   if (laptopCollections.get(laptops.get(groupPosition)).get(childPosition) ...

What is the value of laptops? It is initialized with constructor

public ExpandableListAdapter(Context context, ArrayList<ListObj> laptops ...

on second parameter, it is created on AddMonthlyExpenses.onCreate()

expListAdapter =
   new ExpandableListAdapter(getApplication(), groupList, laptopCollection);

and initially initialized in declaration

 ArrayList<ListObj> groupList= new ArrayList<ListObj>();;

For some reason unknown to me - Android peculiarity - in my case this groupList (or similar member field i had) was NULL even it was initialized on declaration.

But moving the initialization inside onCreate() fixed this problem.

Try that. Or at lease debug the row where laptops is referenced.

Upvotes: 1

Amod Gokhale
Amod Gokhale

Reputation: 2448

Add createCollection(); to button1 setonclick listner

createCollection();

Edit & Delete Working after above line

groupList = new ArrayList(); is written inside for loop might be problem? It creates a new arraylist for each loop and as a result your arraysize is 1 always ( last iteration count )

while (cursor.moveToNext()) {
                groupList = new ArrayList<ListObj>();
                int iD = cursor.getInt(cursor.getColumnIndex("ID"));
                String month = cursor.getString(cursor.getColumnIndex("Month"));
                double budget = cursor.getDouble(cursor.getColumnIndex("Budget"));
                groupList.add(new ListObj(iD,month,budget));
                createCollection();  // for child items
                if (expListAdapter != null) {
                    expListAdapter.add(iD, month, budget);
                    listview.setAdapter(expListAdapter);
                }
            }

change to

groupList = new ArrayList<ListObj>();
while (cursor.moveToNext()) {

                int iD = cursor.getInt(cursor.getColumnIndex("ID"));
                String month = cursor.getString(cursor.getColumnIndex("Month"));
                double budget = cursor.getDouble(cursor.getColumnIndex("Budget"));
                groupList.add(new ListObj(iD,month,budget));
                createCollection();  // for child items
                if (expListAdapter != null) {
                    expListAdapter.add(iD, month, budget);
                    listview.setAdapter(expListAdapter);
                }
            }

Upvotes: 2

Roman Masarovič
Roman Masarovič

Reputation: 199

i think in your code dont work this

laptopCollections.get(laptops.get(groupPosition)).size();

because try find other object instance.

you have so many list in your fragment and adapter you really dont need this. Try keep OOP and refactor this and create better model for this.

or easier way dont use for map key object but id then.

change from Map<ListObj, List<String>> laptopCollections to Map<String,List<String>> laptopCollections where first K is id. Maybe it will be helpfull.

Upvotes: 0

Related Questions