ListView 的position和id的区别

咱们在使用ListView的时候,通常都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener。本文主要在于对OnItemClickListener的position和id参数作详细的解释,我相信有些人在这上面走了些弯路。html

 

先来看一下官方的文档
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 positionView 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的实现java

 

 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_POSITION &&
                  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));
              }
          }
      }
  }
能够看到, position事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,因此,这个位置应该是这个被点击的view在数组[全部的headerView,用户添加的view,全部的 footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId( position)。
 
对于ArrayAdapter的getItemId函数,实现就是return  position。id和 position是一致的。
然而,对于HeaderViewListAdapter

 

public long getItemId(int position) {
      int numHeaders = getHeadersCount();
      if (mAdapter != null && position >= numHeaders) {
          int adjPosition = position - numHeaders;
          int adapterCount = mAdapter.getCount();
          if (adjPosition < adapterCount) {
              return mAdapter.getItemId(adjPosition);
          }
      }
      return -1;
  }
实现逻辑是,若是 position指向了headerView或 footerView,那么返回-1,不然,将返回在用户view数组的位置。
也就是说
id= position-headerView的个数(id < headerviewer的个数+用户view的个数),不然=-1
所以,OnItemClickListener的正确实现以下:

 

void onItemClick(AdapterViewparent, View view, int position, long id){
    if(id == -1) {
        // 点击的是headerView或者footerView
        return;
    }
    int realPosition=(int)id;
    T item=getItem(realPosition);
    // 响应代码
}

 

 

REFERENCES:http://blog.csdn.net/gg137608987/article/details/7995671android

相关文章
相关标签/搜索