Piscean
Piscean

Reputation: 3079

Why am i getting NullPointerException for a CheckedTextView when i click a row after scrolling in ListView?

I have a ListView in my activity. Following is the way i am setting an OnCLickListener on rows of the ListView

 listview.setAdapter(new RowsArrayAdapter(this, rows));

 listview.setOnItemClickListener(new OnItemClickListener() {
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         CheckedTextView ctv = (CheckedTextView) lv.getChildAt(position).findViewById(R.id.row_checkbox);
         ctv.setChecked(true);

 });

getView() method for RowsArrayAdapter is following:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

         LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

         View rowView = inflater.inflate(R.layout.row_layout, parent, false);

         CheckedTextView row = (CheckedTextView) rowView.findViewById(R.id.row_checkbox);
         row.setText(values[position].getRow_no());

         return rowView;
}

It works fine for first 8 rows. I checked the array rows length. Its 16 which is right. But when i scroll down and click on some row for example row 12 then it gives me NullPointerException. Any idea why is that and how can i fix it. Thanks in advance.

Upvotes: 1

Views: 173

Answers (3)

Alexander Mikhaylov
Alexander Mikhaylov

Reputation: 1800

You should not store state in row view itself. Even if you will be able to find the proper row and set a checkbox to checked state, you will have a problem when you will scroll back. To solve this I recommend you to add checked flag in your model and populate checked state in getView method of your adapter. In onClick listener, you will need to modify your model and notifyDataSetChanged on your adapter.

You should not inflate the same view every time in getView method otherwise you will have a very bad performance. You should inflate it only if convertView == null, otherwise just reuse convert view.

I highly recommend you to use RecyclerView instead of listview as it forces to use ViewHolder pattern. Read more here: https://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder

Upvotes: 0

Anjali-Systematix
Anjali-Systematix

Reputation: 1799

This produces null:

CheckedTextView ctv = (CheckedTextView) lv.getChildAt(position).findViewById(R.id.row_checkbox);
ctv.setChecked(true);

But this does not:

CheckedTextView ctv = (CheckedTextView)  lv.getAdapter().getView(position, null,  lv).findViewById(R.id.row_checkbox);
ctv.setChecked(true);

Please try this

Upvotes: 2

Piyush
Piyush

Reputation: 2050

You should use.

 CheckedTextView ctv = (CheckedTextView) view.findViewById(R.id.row_checkbox);

Upvotes: 0

Related Questions