SoFunction
Updated on 2025-03-11

Detailed explanation of the OnItemClickListener of Android ListView

When we use ListView, we usually add a response event to the ListView. This article mainly focuses on giving a detailed explanation of the position and id parameters of OnItemClickListener. I believe some people have taken some detours on this.

Let's take a look at the official documentation first

position The position of the view in the adapter.

id The row id of the item that was clicked.

These two lines do not explain the difference between position and id. In addition, we also have an Adapter getView method.
public abstract View getView (int position, View convertView, ViewGroup parent)
There is also a position here.

Students who have initially come into contact with ListView usually directly inherit ArrayAdapter, and then (for example), they take it for granted that the position of OnItemClick and the position of getView are the same. So we getItem(position) to get the corresponding data.

So is this code wrong? If there is any mistake, what situation will go wrong?

The answer to the first question is that when we add headerView or footerView to the ListView, this code is not necessarily what we want.
The reason for the problem is that when we add headerView or footerView to the ListView, the ListView does something when settingAdapter, which causes the position meaning in Adapter and OnItemClickListener to change.

We can take a look at the implementation of setAdapter in ListView

public void setAdapter(ListAdapter adapter) { 
if (mAdapter != null && mDataSetObserver != null) { 
(mDataSetObserver); 
} 
resetList(); 
(); 
if (() > 0|| () > 0) { 
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); 
} else { 
mAdapter = adapter; 
} 

It can be seen that if this ListView has a headerView or footerView, then a layer of HeaderViewListAdapter will be encapsulated outside the adapter we passed in. This is an adapter specially used to automatically process headerView and footerView. In ListView, the headerView and footerView are not distinguished. ListView can be understood as a UI (ViewGroup) that is only responsible for managing an array of a group of Views. HeaderView and footerView are both delegated to HeaderViewListAdapter for processing. (We can also see why the API documentation mentions that addFooterView and addHeaderView must be called before the setAdapter function. If called later, the HeaderViewListAdapter will not be generated, resulting in the headerView and footerView not being displayed).

Going back to the question at the beginning, what is the difference between position and id? To do this, let's find out how position and id are transmitted.

OnItemClickListener is called in the public boolean performItemClick(View view, int position, long id) function.

performItemClick is called in()

private class PerformClick extends WindowRunnnable implements Runnable { 
int mClickMotionPosition; 
public void run() { 
// The data has changed since we posted this action in the event queue, 
// bail out before bad things happen 
if (mDataChanged) return; 
final ListAdapter adapter = mAdapter; 
final int motionPosition = mClickMotionPosition; 
if (adapter != null && mItemCount > 0 && 
motionPosition != INVALID_<strong>POSITION</strong> && 
motionPosition < () && sameWindow()) { 
final View view = getChildAt(motionPosition - mFirstPosition); 
// If there is no view, something bad happened (the view scrolled off the 
// screen, etc.) and we should cancel the click 
if (view != null) { 
performItemClick(view, motionPosition, (motionPosition)); 
} 
} 
} 
} 

As you can see, position is actually the position of the view that is clicked in the ListView. Note that in ListView, it is not responsible for handling headerView and footViewer, so this position should be the position of the clicked view in the array [all headerViews, user added views, and all footerViews] (please refer to the getView implementation of HeaderViewListAdapter for yourself). And id comes from (position).
For the getItemId function of ArrayAdapter, the implementation is return position. The id and position are consistent.

However, for HeaderViewListAdapter

public long getItemId(int <strong>position</strong>) { 
int numHeaders = getHeadersCount(); 
if (mAdapter != null && <strong>position</strong> >= numHeaders) { 
int adjPosition = <strong>position</strong> - numHeaders; 
int adapterCount = (); 
if (adjPosition < adapterCount) { 
return (adjPosition); 
} 
} 
return -1; 
} 

The implementation logic is that if the position points to the headerView or footerView, then -1 is returned, otherwise, the position in the user view array will be returned.
That is to say

id=position-headerView number (id < number of headerviewer + number of user view), otherwise =-1

Therefore, the correct implementation of OnItemClickListener is as follows:

void onItemClick(AdapterViewparent, View view, int &lt;strong&gt;position&lt;/strong&gt;, long id){ 
if(id == -1) { 
// Click on headerView or <strong>footerView</strong>return; 
} 
int realPosition=(int)id; 
T item=getItem(realPosition); 
// Response code}

Related readings:

Analysis of the reason why ListView setOnItemClickListener click invalid in Android

The above is a detailed explanation of the OnItemClickListener of Android ListView introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support for my website!