本文參考自:http://blog.csdn.net/zxt0601/article/details/52562770
(先說點題外話,這博主很不錯了,他的文章在hongyangAndroid (鴻洋)的公衆號的發佈過多次了,文章不僅有技術含量,而且文筆很細膩)
這次學習的是一個與RecyclerView有關的工具類——DiffUtil,具體的內容請看上文。我在這裏主要是就文章的一些點提出自己的見解:
1、在模擬刷新的onRefresh()方法中。有這麼一段代碼:
mNewDatas = new ArrayList<>();
for (TestBean bean : mDatas) {
mNewDatas.add(bean.clone());//clone一遍舊數據 ,模擬刷新操作
}
//mNewDatas.addAll(mDatas); //++++++++++
mNewDatas.add(new TestBean("趙子龍", "帥", R.drawable.pic6));//模擬新增數據
mNewDatas.get(0).setDesc("Android+++++");
mNewDatas.get(0).setPic(R.drawable.pic7);//模擬修改數據
TestBean testBean = mNewDatas.get(1);//模擬數據位移
mNewDatas.remove(testBean);
mNewDatas.add(0,testBean);
在註釋裏有講解,clone一遍舊數據 ,模擬刷新操作
,這裏需要注意,新的數據需要深度clone(生成一個新的與原來TestBean實例具有相同內容的成員變量的實例,如果不懂請看演示圖),否則mNewDatas與mDatas對於“一個相同的TestBean實例(成員變量的內容相同)”存在同一引用,從而導致改變mNewDatas的某一項的成員變量的內容,由於存在統一引用,mDatas中的那一項也會跟着改變,因此areContentsTheSame()是不起作用的, 大家也可以自己去嘗試一下,就像我註釋掉的那行代碼(把原來的操作註釋掉),雖然是new了一個新的mNewDatas,但是通過mNewDatas.addAll(mDatas)方法填充的數據,在未做其他操作的前提下,mNewDatas與mDatas中的每一項數據都具有相同的引用,說白了就是同一東東。(其實這一點在文章末尾也有提到,但具體的就是上面的意思)。(題外話:這裏是在用空間換效率)
演示圖(第一張的爲正確的,第二張爲非正確的):
2、 在使用博主提供的Demo時,如果是按照文章的順序一步一步看下去的,則在第2步DiffUtil的簡單用法
時,想要運行demo體驗演示效果的話,需要把DiffCallBack.java
中的getChangePayload(int oldItemPosition, int newItemPosition)
方法與DiffAdapter
中的onBindViewHolder(DiffVH holder, int position, List<Object> payloads)
方法註釋掉,再去運行,因爲這是第3部分DiffUtil的高級用法
的內容了。開始我就沒有注意到,就直接運行了,然後就沒有體驗到博主所說的“白光一閃”。(搞得我一直以爲是我眼花,看不出來#_#)
番外篇:
在前面的文章中有提到過一個名詞“定向刷新”,如果對這個有疑惑的,可以看看這個:
【Android】 RecyclerView、ListView實現單選列表的優雅之路.
在這裏面,有用實際了代碼講解什麼是“定向刷新”。
值得注意的是在三 ListView 方案一覽:
的 2 ListView裏尋找優雅之路:
中,核心代碼如下(從考慮了HeaderView的情況
這裏就可以體現出作者的細膩):
//如果 當前選中的View 在當前屏幕可見,且不是自己,要定向刷新一下之前的View的狀態
if (position != mSelectedPos) {
int firstPos = mLv.getFirstVisiblePosition() - mLv.getHeaderViewsCount();//這裏考慮了HeaderView的情況
int lastPos = mLv.getLastVisiblePosition() - mLv.getHeaderViewsCount();
if (mSelectedPos >= firstPos && mSelectedPos <= lastPos) {
View lastSelectedView = mLv.getChildAt(mSelectedPos - firstPos);//取出選中的View
CouponVH lastVh = (CouponVH) lastSelectedView.getTag();
lastVh.ivSelect.setSelected(false);
}
//不管在屏幕是否可見,都需要改變之前的data
mDatas.get(mSelectedPos).setSelected(false);
//改變現在的點擊的這個View的選中狀態
couponVH.ivSelect.setSelected(true);
mDatas.get(position).setSelected(true);
mSelectedPos = position;
}
在上面的代碼中,有View lastSelectedView = mLv.getChildAt(mSelectedPos - firstPos);
,這裏是爲了獲取先前被選中的view,這裏用到了ListView的getChildAt()方法,其作用就是取得在屏幕上可見的items中指定index的view,不過這裏index基數爲0,即第一個可見的item的index爲0,依次類推,而不是基於整個ListView的第一個item來說的,如下圖:
另外,還需要注意一下末尾的評論,如果有出現評論中的狀況的: