When I am adding section header in my listview I got nullpointerexception error when I am scrolling a listview.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.arrayadapter, PID: 20681
java.lang.NullPointerException: Attempt to read from field 'android.widget.TextView com.arrayadapter.ABCArrayAdapter$ViewHolderHeader.header' on a null object reference
at com.arrayadapter.ABCArrayAdapter.getView(ABCArrayAdapter.java:185)
at android.widget.AbsListView.obtainView(AbsListView.java:2929)
at android.widget.ListView.makeAndAddView(ListView.java:1945)
at android.widget.ListView.fillDown(ListView.java:719)
at android.widget.ListView.fillGap(ListView.java:683)
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:7293)
at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:4391)
at android.widget.AbsListView.onTouchMove(AbsListView.java:5782)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:5610)
at android.view.View.dispatchTouchEvent(View.java:9993)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2830)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2501)
at android.widget.AbsListView.dispatchTouchEvent(AbsListView.java:5547)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2841)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2516)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2831)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1863)
at android.app.Activity.dispatchTouchEvent(Activity.java:3046)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2792)
at android.view.View.dispatchPointerEvent(View.java:10228)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5345)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5181)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4621)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4674)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4640)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4782)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4648)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4839)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4621)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4674)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4640)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4648)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4621)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7307)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7185)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7146)
at android.view.ViewRootImpl$Wind
Here is my arrayadapter class code.(updated after @RachitSolanki's suggestions)
public class ABCArrayAdapter extends ArrayAdapter<ABCModel> {
Context context;
ArrayList<ABCModel> selectedlocation;
public ArrayList<String> locationid = new ArrayList<String>();
public String primarylocation = "null";
int clickedRadioButtonPosition = -1;
ViewHolder viewHolder = null;
ViewHolderHeader viewHolderHeader = null;
public ABCArrayAdapter(Context context, int resourceId, ArrayList<ABCModel> selectedlocation) {
super(context, resourceId, selectedlocation);
this.context = context;
this.selectedlocation = new ArrayList<ABCModel>();
this.selectedlocation.addAll(selectedlocation);
}
public int getCount() {
return this.selectedlocation.size();
}
public ABCModel getItem(int position) {
return this.selectedlocation.get(position);
}
public long getItemId(int position) {
return this.selectedlocation.get(position).hashCode();
}
// View lookup cache
private static class ViewHolder {
TextView name;
TextView home;
CheckBox chk_locationlist;
RadioButton rbt_primarylocation;
}
private static class ViewHolderHeader {
TextView txt_header;
}
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
if (getItem(position).isSectionHeader()) {
return 0;
} else {
return 1;
}
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
int type = getItemViewType(position);
if (type == 0) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.section_header, null);
viewHolderHeader = new ViewHolderHeader();
viewHolderHeader.txt_header = (TextView) convertView.findViewById(R.id.section_header);
convertView.setTag(viewHolderHeader);
viewHolder = null;
} else {
viewHolderHeader = (ViewHolderHeader) convertView.getTag(R.layout.section_header);
viewHolder = null;
}
} else if (type == 1) {
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
convertView = mInflater.inflate(R.layout.ABC_list_item_name, null);
viewHolder = new ViewHolder();
viewHolder.name = (TextView) convertView.findViewById(R.id.txt_ha_name);
viewHolder.home = (TextView) convertView.findViewById(R.id.txt_ha_town);
viewHolder.chk_locationlist = (CheckBox) convertView.findViewById(R.id.chk_box_ha_list);
viewHolder.rbt_primarylocation = (RadioButton) convertView.findViewById(R.id.rbtn_pl);
viewHolder.rbt_primarylocation.setPaintFlags(viewHolder.rbt_primarylocation.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
viewHolder.chk_locationlist.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
View finalConvertView = (View) v.getParent();
RadioButton rbt_primarylocation = (RadioButton) finalConvertView.findViewById(R.id.rbtn_pl);
int pos = (Integer) v.getTag();
ABCModel _state = (ABCModel) selectedlocation.get(pos);
if (cb.isChecked()) {
_state.setSelected(cb.isChecked());
// Update ArrayList
selectedlocation.remove(pos);
selectedlocation.add(pos, _state);
locationid.add(_state.getId().toString());
rbt_primarylocation.setVisibility(View.VISIBLE);
if (locationid.size() == 1) {
rbt_primarylocation.setChecked(true);
primarylocation = _state.getId().toString();
rbt_primarylocation.setText("This is my primary location.");
rbt_primarylocation.setPaintFlags(0);
System.out.println("Primary Location---" + primarylocation);
}
} else {
_state.setSelected(false);
locationid.remove(_state.getId().toString());
// When unchecked the one with radio button selected
if (rbt_primarylocation.isChecked()) {
if (locationid.size() > 0) {
//rbt_primarylocation.setChecked(true);
rbt_primarylocation.setText("Make this my primary location.");
rbt_primarylocation.setPaintFlags(rbt_primarylocation.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
primarylocation = "null";
Toast.makeText(
v.getContext(),
"Please select a Primary Location", Toast.LENGTH_LONG).show();
}
}
rbt_primarylocation.setVisibility(View.INVISIBLE);
}
}
});
viewHolder.rbt_primarylocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickedRadioButtonPosition = (Integer) v.getTag();
ABCModel _state = (ABCModel) selectedlocation.get(clickedRadioButtonPosition);
primarylocation = _state.getId().toString();
viewHolder.rbt_primarylocation.setText("This is my primary location.");
viewHolder.rbt_primarylocation.setPaintFlags(0);
System.out.println("Primary Location---" + primarylocation);
notifyDataSetChanged();
}
});
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
viewHolderHeader = null;
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag(R.layout.search_expand_item);
viewHolderHeader = null;
}
}
if(type == 0)
{
ABCModel state = selectedlocation.get(position);
viewHolderHeader.txt_header.setText(state.getRegion());
}else
{
ABCModel state = selectedlocation.get(position);
viewHolder.name.setText(state.getName());
viewHolder.home.setText(state.getAddress1() + "\r\n" + state.getCity() + ", " + state.getState() + " " + state.getZip());
viewHolder.chk_locationlist.setChecked(state.isSelected());
// Set views for view recycling on scrolling
if (viewHolder.chk_locationlist.isChecked()) {
viewHolder.rbt_primarylocation.setVisibility(View.VISIBLE);
} else {
viewHolder.rbt_primarylocation.setVisibility(View.INVISIBLE);
}
if (position == clickedRadioButtonPosition) {
viewHolder.rbt_primarylocation.setChecked(true);
viewHolder.rbt_primarylocation.setText("This is my primary location.");
viewHolder.rbt_primarylocation.setPaintFlags(0);
} else {
viewHolder.rbt_primarylocation.setChecked(false);
viewHolder.rbt_primarylocation.setText("Make this my primary location.");
viewHolder.rbt_primarylocation.setPaintFlags(viewHolder.rbt_primarylocation.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
viewHolder.chk_locationlist.setTag(position);
viewHolder.rbt_primarylocation.setTag(position);
}
return convertView;
}
}
When you store the viewHolderHeader in the tag you use this line of code:
but when you get the viewHolderHeader back, you use a key to return it:
I'm not sure these would match up, you need to use the same key in the first line:
https://developer.android.com/reference/android/view/View.html#getTag(int)