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

相關文章
相關標籤/搜索