2015-04-16 30 views
65

由於新支持庫版本(22.x)的RecyclerView.ViewHolder類的getPosition()方法已被棄用,而不是本主題中提及的方法。我從閱讀文檔中看不出真正的區別。 請問有人可以解釋一下外行人的不同之處嗎?RecyclerView.ViewHolder - getLayoutPosition vs getAdapterPosition

我有以下用例 - 我給我的適配器一個列表,並且還希望能夠爲每個列表項目關聯額外的信息。我有一個位置到額外的映射,並且這個映射對持有者是可用的,這樣他們就可以爲他們的位置獲取額外的東西並且用它來做東西。在持有者中,我應該使用哪種方法?

當索引0和1處的列表項交換時,持有者位置會發生什麼?這些方法返回什麼?

回答

78

這是一個棘手的情況,對不起,文檔是不夠的。

當適配器內容更改(並且您調用notify***())時,RecyclerView會請求新的佈局。從那一刻起,直到佈局系統決定計算新佈局(< 16毫秒),佈局位置和適配器位置可能不匹配,因爲佈局尚未反映適配器更改。

在您的用例中,由於您的數據與您的適配器內容相關(並且我認爲數據在適配器更改的同時發生了更改),因此您應該使用adapterPosition

但要小心,如果您打電話notifyDataSetChanged(),因爲它使所有內容無效,RecyclerView不知道ViewHolder的適配器位置,直到計算下一個佈局。在這種情況下,getAdapterPosition()將返回RecyclerView#NO_POSITION-1)。

但讓我們說如果你叫notifyItemInserted(0),以前位於0的ViewHolder的getAdapterPosition()將立即開始返回1。所以只要你調度細粒度的通知事件,你總是處於良好的狀態(即使新的佈局尚未計算,我們知道適配器的位置)。

另一個例子,如果你正在做用戶點擊的東西,如果getAdapterPosition()回報NO_POSITION,最好忽略點擊,因爲你不知道什麼點擊用戶(除非你有一些其他的機制,例如穩定的ID查找該項目)。

編輯在佈局位置爲好

比方說,你正在使用LinearLayoutManager,並希望訪問當前點擊項目上面的ViewHolder。在這種情況下,您應該使用佈局位置來獲取上面的項目。

mRecyclerView.findViewHolderForLayoutPosition(myViewHolder.getLayoutPosition() - 1) 

您必須使用佈局位置,因爲它與用戶當前在屏幕上看到的內容相匹配。

+1

我玩了一下,結果getAdapterPosition()方法總是返回-1。我調試它,原因是方法中的代碼(最終ViewParent父= itemView.getParent();如果(!(父)instanceofofRecyclerView){返回-1;}總是進入if塊,即回收視圖不是我的單元格視圖的父級,它怎麼可能?我創建持有者的代碼是:return MyViewHolder(LayoutInflater.from(viewGroup.getContext())。inflate(R.layout.test_list_item,viewGroup,false)); (繼續另一條評論。) – wujek

+0

當我更改代碼來調用inflate(R.layout.test_list_item,viewGroup,true); (注意'attach to root'),Android拋出:java.lang.IllegalStateException:指定的子項已經有父項。您必須先調用子對象的父對象的removeView()。那麼創建視圖持有人的正確方法是什麼?正確地附加到回收視圖的視圖是什麼?奇怪的是,即使getAdapterPosition()返回-1,因爲父母爲空,所有其他工作正常。 – wujek

+1

佈局充氣器中的布爾參數是「addToParent」。它必須是錯誤的,因爲LayoutManager有責任添加它。 我想你在onBind中調用了getAdapterPosition,你已經通過了這個位置。從技術上講,視圖持有者在onBind返回後表示該位置。 順便說一句,我們已經更新getAdapter的位置來返回一個有效的位置(如果可能的話),即使它是分離的,它很快就會發布。 – yigit

相關問題