Custom ArrayAdapter messed up views, with NullPointerException
I am currently developing a content creation app for Android. The main purpose is to give the user the ability to generate a list from text and image records (presented at the end with EditText and ImageView).
I connected this list to ListView by writing a custom ArrayAdapter using the ViewHolder template
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// get current Entry
Entry e = getItem(position);
// variable for holding the view
ViewHolder holder;
// check if there is no view created
if (convertView == null) {
// prepare holder for view to be saved in
holder = new ViewHolder();
// get layout inflater
LayoutInflater inflater = (LayoutInflater) super.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// if current entry is an image entry
if (e.getType().equals(Entry.Type.IMAGE_ENTRY)) {
// inflate layout with ImageView
convertView = inflater.inflate(R.layout.image_list_item,
parent, false);
ImageView iView = (ImageView) convertView
.findViewById(R.id.imageDisplay);
// save inflated view in holder
holder.imageViewItem = iView;
// store the holder with the view
convertView.setTag(holder);
// if it is a text entry
} else if (e.getType().equals(Entry.Type.TEXT_ENTRY)) {
// inflate layout with EditText
convertView = inflater.inflate(R.layout.text_list_item, parent,
false);
EditText tView = (EditText) convertView
.findViewById(R.id.textField);
// save inflated view in holder
holder.editTextItem = tView;
// store the holder with the view
convertView.setTag(holder);
}
} else {
// get holder from existing view
holder = (ViewHolder) convertView.getTag();
}
if (e != null) {
if (e.getType().equals(Entry.Type.IMAGE_ENTRY)) {
// load corresponding image
holder.imageViewItem.setImageBitmap(((ImageEntry) e).getImage());
} else if (e.getType().equals(Entry.Type.TEXT_ENTRY)) {
// load corresponding text
holder.editTextItem.setText(((TextEntry) e).getText());
}
}
return convertView;
}
Contrary to the tutorials and examples I've seen, I need to differentiate between layouts that I'm inflating due to the differences between texts and images. And this seems to be causing some problems because sometimes after adding different entries after another I get these exceptions
E/AndroidRuntime(15812): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
E/AndroidRuntime(15812): at <project>.util.EntryListAdapter.getView(EntryListAdapter.java:104)
So, it seems to me that the method is being called in the wrong representation, because otherwise there must be an object of type EditText. I'm not really sure when the ListView launches all of its views, and I'm experimenting with my adapter and listing a lot, but I can't figure out why this sometimes clogs up calls to my records. Can anyone help me?
source to share
if you don't override getViewTypeCount
, you only get one null convertView
, so you initialize it with image_list_item.xml
or text_list_item.xml
. If you want to handle different types of views, override
public int getViewTypeCount() {
return 2;
}
to handle two different types of views, and getItemViewType
public int getItemViewType (int position) {
Entry e = getItem(position);
if (e.getType().equals(Entry.Type.IMAGE_ENTRY)) {
return 0;
}
return 1;
}
and in getView
check the return valuegetItemViewType
source to share
The Sample ViewHolder for ListView should be used when you know the item view types before getting started. If they dynamically change when new positions are added (in fact, if notifyDataSetChanged()
called), then there are problems with processing.
For dynamically changing collections with different view types, it is better to use RecyclerView
source to share