Here is some code, that I cannot fix myself.
I made a custom ArrayAdapter, to populate my ListView with TextViews containing players' names.
It works as intended when the whole list of player names is specified before the adapter is instantiated. The problem occurs when I click on a list item added after adapter instantiation.
I cant figure out why I get a NullPointerException in:
PlayersArrayAdapter.getItemId(int position)
on this line:
return mIdMap.get(item);
when I click the third player named "Fries" on the list.
Code with explanations:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_match_settings);
//arraylist to store players names
ArrayList<String> playerNames = new ArrayList<String>();
//players which are on the list from the begining
//when I click on them, "onPlayerListItemClicked" is properly called
//and I get clicked player name in my LogCat
playerNames.add("Pawel");
playerNames.add("Olga");
//listview to display players names
ListView playerListView = (ListView)findViewById(R.id.ms_player_list);
//custom arrayadapter, which gets ArrayList as one of arguements
PlayersArrayAdapter playerListAdapter = new PlayersArrayAdapter(this, R.layout.player_list_item, playerNames);
playerListView.setAdapter(playerListAdapter);
playerListView.setOnItemClickListener(onPlayerListItemClicked);
// THERE IS ROOT OF PROBLEM:
// player "Fries" is also added to the ListView, and is properly displayed
// but when I click on it, I get NullPointerException described above
playerNames.add("Fries");
playerListAdapter.notifyDataSetChanged();
}
OnItemClickListener onPlayerListItemClicked = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
String item = (String)parent.getItemAtPosition(position);
Logger.i("Clicked at item: " + item);
}
};
PlayersArrayAdapter class:
class PlayersArrayAdapter extends ArrayAdapter<String>{
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public PlayersArrayAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
for (int i = 0; i < objects.size(); i++)
mIdMap.put(objects.get(i), i);
}
@Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item); //at this line NullPointerException throws
}
@Override
public boolean hasStableIds() {
return true;
}
}
Error message from Debug:
Thread [<1> main] (Suspended (exception NullPointerException))
<VM does not provide monitor information>
PlayersArrayAdapter.getItemId(int) line: 119
AbsListView$PerformClick.run() line: 1964
ViewRoot(Handler).handleCallback(Message) line: 587
ViewRoot(Handler).dispatchMessage(Message) line: 92
Looper.loop() line: 130
ActivityThread.main(String[]) line: 3687
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 507
ZygoteInit$MethodAndArgsCaller.run() line: 867
ZygoteInit.main(String[]) line: 625
NativeStart.main(String[]) line: not available [native
@Override
public long getItemId(int position) {
return position // this needs to just return a long, position usually is best choice
}