Android ListView的的OnItemClickListener详解详解
我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener。本文
主要在于对OnItemClickListener的position和id参数做详细的解释,我相信有些人在这上面走了些弯路。
先来看一下官方的文档
position The position of the view in the adapter.
id The row id of the item that was clicked.
而这两行字并没有解释清楚position和id的区别。另外,我们还有个Adapter的getView方法。
public abstract View getView (int position, View convertView, ViewGroup parent)
这里也有一个position。
初步接触ListView的同学,一般会直接继承ArrayAdapter,然后(比如我),就想当然的认为OnItemClick的position和
getView的position是一样的啊。于是我们就getItem(position)来获取相应的数据。
那么这段代码有没有错呢?如果有错的话,在什么情况会出错呢?
第一个问题的答案是,当我们为ListView添加headerView或者footerView之后,这段代码就不一定是我们想要的了。
出现问题的原因在于,当我们为ListView添加headerView或者footerView之后,ListView在setAdapter时,做了一些事情,这
导致,Adapter和OnItemClickListener中的position含义发生了变化。
我们可以来看看ListView中setAdapter的实现
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
可以看出,如果这个ListView存在headerView或者footerView的话,那么会在我们传入的adapter外面在封装一层
HeaderViewListAdapter,这是一个专门用来自动处理headerView和footerView的adapter。在ListView中,本身不区分
headerView,footerView。ListView可以理解成是只负责管理一组View的数组的UI(ViewGroup),headerView和footerView
都委托给HeaderViewListAdapter来处理。(从这里也可以看到为什么API文档中提到,addFooterView和addHeaderView要在
setAdapter函数之前调用,如果在之后调用,那么就不会生成HeaderViewListAdapter,从而导致显示不出headerView和
footerView)。
回到开头的问题,position和id有啥区别。为此,我们找一下position和id是怎么传进来的。
OnItemClickListener在android.widget.AdapterView的public boolean performItemClick(View view, int position, long id)函数中
被调用。
performItemClick在android.widget.AbsListView.PerformClick.run() 中被调用
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 < adapter.getCount() && 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, adapter.getItemId(motionPosition));
}
}
}
}
评论0
最新资源