1. 程式人生 > >RecyclerView使用之——資料重新整理混亂及解決方案

RecyclerView使用之——資料重新整理混亂及解決方案

初學Android,首次在專案中運用發生了RecyclerView刷新發生混亂的問題,困擾好久,終於解決,分享如下。

【問題現象】

專案中用RecyclerView做了一個醫生排班列表,用於顯示所有醫生的排班資訊,RecyclerView的一個專案(即一個醫生),可以通過點前一週,下一週按鈕檢視不同周次的該醫生的排班情況,編碼很順利,網上很多RecyclerView的例子,但在測試時發現,當第一次點選其中一個醫生的下一週按鈕時,結果該醫生的資料卻沒有重新整理,前一個醫生的資料卻被重新整理了。

【調查過程】

通過debug發現了以下有趣的事情,在onBindViewHolder方法中,下一週按鈕被點選時,被點選按鈕所在專案(即holder物件)的ID假設為A,位置(即position)假設為7,在按鈕事件被觸發,通過Adapter.notifyDataSetChanged();觸發RecyclerView重新整理後,onBindViewHolder方法執行的時候,發現ID為A的holder的position發生了變更,不再是7了,而變成了6。holder的順序發生了變更,但是adapter所繫結的資料的順序卻很正常,沒發生變更,而這導致了上述現象的發生。

到底是什麼原因導致position發生了變更呢?會不會是大牛的google開發人員的bug呢?如果是的話,android的開發者成千上萬,早就發現這個問題並被反映解決了,又怎麼能輪得到咱中大獎呢?所以說問題的原因很有可能是自己使用不當。但畢竟是android菜鳥,怎麼解決毫無頭緒,還是debug進原始碼看看到底為什麼position會發生變更吧。我發現holder物件是在RecyclerView的getViewForPosition(int position)方法中被生成的。再往下細看,發現有一行給holder賦值的判斷條件if (mAdapter.hasStableIds())沒能走進去。我感覺很蹊蹺,看看StableIds是個什麼東西,有什麼作用吧。hasStableIds()方法的註釋如下:

/**
 * Returns true if this adapter publishes a unique <code>long</code> value that can
 * act as a key for the item at a given position in the data set. If that item is relocated
 * in the data set, the ID returned for that item should be the same.
 *
 * @return true if this adapter's items have stable IDs
*/
寫得很明確,感覺自己的問題就是它導致的。問題定位到這裡,很容易查到了許多類似的問題和解決方法。如下:

【解決方法】

首先,在繫結adapter給RecycleView之前,設定adapter的stableIds為true。

adapter.setHasStableIds(true);
recyclerView.setAdapter(adapter);

其次,在adapter中,需要重寫getItemId方法。

@Override
public long getItemId(int position) {
    return position;
}
之後重新執行app,發現問題完美解決了。
更多RecyclerView的問題,可參閱如下文章。
http://blog.csdn.net/limonzet/article/details/56665727