CHarris
CHarris

Reputation: 2803

How can I get checkboxes working in my listview?

I've been trying to follow tutorials/ posts on S.O on how to get my checkbox working in my listview. Lots of stuff I want to do with it but first I want to simply get the position of the item checked but the app crashes and I get a NullPointerException error.

The error is (with more stuff below this part) :

    java.lang.NullPointerException at com.example.chris.tutorialspoint.SelectPhoneContactAdapter.getView(SelectPhoneContactAdapter.java:104)

And line 104 is :

convertView.setTag(v);

But to me it looks like I've been following the tutorials properly and I don't know how to adapt these posts to my problem: Getting NullPointerException in custom ListView and Crash in ListView at AbsListView.obtainView for ListActivity. Can you tell me what is wrong? Everything worked well until I started experimenting with these checkboxes.

Here is my customadapter code, SelectPhoneContactAdapter:

public class SelectPhoneContactAdapter extends BaseAdapter {

    //define a list made out of SelectPhoneContacts and call it theContactsList
    public List<SelectPhoneContact> theContactsList;
    //define an array list made out of SelectContacts and call it arraylist
    private ArrayList<SelectPhoneContact> arraylist;
    boolean itemChecked[];
    Context _c;

    //define a ViewHolder to hold our name and number info, instead of constantly querying
    // findviewbyid. Makes the ListView run smoother
    ViewHolder v;

    public SelectPhoneContactAdapter(final List<SelectPhoneContact> selectPhoneContacts, Context context) {
        theContactsList = selectPhoneContacts;
        _c = context;
        this.arraylist = new ArrayList<SelectPhoneContact>();
        this.arraylist.addAll(theContactsList);
        itemChecked = new boolean[theContactsList.size()];

    }


    @Override
    public int getCount() {
        System.out.println("the amount in arraylist :" + arraylist.size());
        return arraylist.size();
    }

    @Override
    public Object getItem(int i) {
        return theContactsList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)

    static class ViewHolder {
        //        In each cell in the listview show the items you want to have
//        Having a ViewHolder caches our ids, instead of having to call and load each one again and again
        TextView title, phone;
        CheckBox check;
    }

    @Override
    public View getView(final int i, View convertView, ViewGroup viewGroup) {

        //we're naming our convertView as view
        View view = convertView;


        if (view == null) {

            v = new ViewHolder();
            System.out.println("getview position :" + i);

            //if there is nothing there (if it's null) inflate the view with the layout
            LayoutInflater li = (LayoutInflater) _c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = li.inflate(R.layout.phone_inflate_listview, null);


            //      So, for example, title is cast to the name id, in phone_inflate_listview,
//        phone is cast to the id called no etc
            v.title = (TextView) view.findViewById(R.id.name);
            v.phone = (TextView) view.findViewById(R.id.no);
            v.check = (CheckBox) view.findViewById(R.id.checkBoxContact);

            convertView.setTag(v);

            //or else use the view (what we can see in each row) that is already there
        } else {
            view = convertView;

        }


//        store the holder with the view
        final SelectPhoneContact data = (SelectPhoneContact) theContactsList.get(i);

        //in the listview for contacts, set the name
        v.title.setText(data.getName());
        //in the listview for contacts, set the number
        v.phone.setText(data.getPhone());
        v.check.setChecked(false);

        v.check.setChecked(itemChecked[i]);

        v.check
                .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                                                 boolean isChecked) {
                        itemChecked[i] = isChecked;
                    }
                });

        // Return the completed view to render on screen
        return view;


    }
}

My getters and setters, SelectPhoneContact:

public class SelectPhoneContact {

    String phone;

    public String getPhone() {return phone;}

    public void setPhone(String phone) {
        this.phone = phone;
    }

    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    Boolean selected;

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected){
        this.selected=selected;
    }
}

I can post more code if necessary.

Upvotes: 0

Views: 56

Answers (1)

Ben P.
Ben P.

Reputation: 54264

Consider this code:

@Override
public View getView(final int i, View convertView, ViewGroup viewGroup) {
    ...
    View view = convertView;

    if (view == null) {
        ...
        view = li.inflate(R.layout.phone_inflate_listview, null);
        ...
        convertView.setTag(v);
    }
    ...
}

First you assign the value of convertView to your view variable. When it is null, you branch into the if statement, where you assign a new value to view via li.inflate().

However, you then reference convertView later inside this if statement. Despite the fact that you wrote view = convertView above, at this point convertView is still null.

There are two ways to fix this. The first option is to simply change convertView.setTag(v) to view.setTag(v). The other is to delete this line:

View view = convertView;

And simply change any place you reference view to use convertView instead. There's no need to introduce a new View view variable; you can just work with convertView directly.

Upvotes: 1

Related Questions