Reputation: 972
I am using the attached class in viewholder patern to instantiate and reuse my item views each time i try to work woth adapters
anyways whenever am trying to set the view text to certain value it crashes giving that the view is null
public class SpinnerServicesAdapter extends ArrayAdapter<MyService> {
private LayoutInflater inflater;
private Context mContext;
private ArrayList<MyService> services;
private String headerTxt;
public SpinnerServicesAdapter(Context mContext, int textViewResourceId, ArrayList services, String headerTxt) {
super(mContext, textViewResourceId, services);
this.mContext = mContext;
this.services = services;
this.headerTxt = headerTxt;
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
SpinnerViewHolder spinnerViewHolder;
if (convertView == null) {
if (position == 0) {
convertView = inflater.inflate(R.layout.spinner_header_item_two, parent, false);
} else {
convertView = inflater.inflate(R.layout.spinner_item_two, parent, false);
}
spinnerViewHolder = new SpinnerViewHolder(convertView);
convertView.setTag(spinnerViewHolder);
} else {
spinnerViewHolder = (SpinnerViewHolder) convertView.getTag();
}
if (position == 0) {
spinnerViewHolder.txtVue.setText(headerTxt);
} else {
spinnerViewHolder.txtVue.setText(services.get(position).getName_en());
}
return convertView;
}
class SpinnerViewHolder {
TextView txtVue;
public SpinnerViewHolder(View v) {
txtVue = (TextView) v.findViewById(R.id.spinner_item_two);
}
}
}
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.infovas.hanger.adapters.SpinnerServicesAdapter.getCustomView(SpinnerServicesAdapter.java:60)
at com.infovas.hanger.adapters.SpinnerServicesAdapter.getView(SpinnerServicesAdapter.java:42)
at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:197)
at android.widget.Spinner.onMeasure(Spinner.java:507)
at android.support.v7.widget.AppCompatSpinner.onMeasure(AppCompatSpinner.java:416)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1083)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:615)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17548)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5478)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2632)
at android.view.View.measure(View.java:17548)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2125)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1238)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1455)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1126)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6041)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:792)
at android.view.Choreographer.doCallbacks(Choreographer.java:596)
at android.view.Choreographer.doFrame(Choreographer.java:557)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:778)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
Upvotes: 1
Views: 926
Reputation: 5371
You are using one ViewHolder
for two different adapter layouts, this what produces nullable views, alternatively, you may override getItemViewType
method in your Adapter
to determine Header Item and Normal Item like this:
1- Define those constants in your adapter class:
private final int TYPE_HEADER = 0;
private final int TYPE_ITEM = 1;
2- Override the getItemViewType(int position)
method in your adapter:
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
3- Create a ViewHolder
class for Header Items:
class SpinnerHeaderViewHolder {
TextView txtHeader;
public SpinnerHeaderViewHolder(View v) {
txtHeader= (TextView) v.findViewById(R.id.spinner_header_item_text_view);
}
}
Don't forget to refer the 'txtHeader' to the correct id in your (header layout)
4- Now in your getCustomView(int position, View convertView, @NonNull ViewGroup parent)
method, do this:
public View getCustomView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
final int itemType = getItemViewType(position);
if (convertView == null) {
if (itemType == TYPE_HEADER) {
convertView = inflater.inflate(R.layout.spinner_header_item_two, parent, false);
viewHolder = new SpinnerHeaderViewHolder(convertView);
} else {
convertView = inflater.inflate(R.layout.spinner_item_two, parent, false);
viewHolder = new SpinnerViewHolder(convertView);
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
if (position == 0) {
((SpinnerHeaderViewHolder) viewHolder).txtHeader.setText(headerTxt);
} else {
((SpinnerViewHolder) viewHolder).txtVue.setText(services.get(position).getName_en());
}
return convertView;
}
Hope this will help.
Upvotes: 1
Reputation: 41
Are you sure that the textview having as id "spinner_item_two" exists in both files "spinner_header_item_two.xml" and "spinner_item_two.xml ?
Upvotes: 0
Reputation: 8386
First, the issue is that (TextView) v.findViewById(R.id.spinner_item_two)
return null
(== don't find the view with id R.id.spinner_item_two
in v
). You have to check that this ID is correct in your XML layout.
Secondly, you inflate different view by the position. The problem is that the framework will reuse it without distinction. You have to override getItemViewType(int position)
for returning two int, one for each type of view.
Finally, the framework give us a more beautiful method to do with RecyclerView
. If you have time, check it.
Upvotes: 1