轉(zhuǎn)載請(qǐng)注明出處:http://www.itdecent.cn/p/3397c4e155e5
本文出自Shawpoo的簡(jiǎn)書
我的博客:CSDN博客
問題描述
這兩天在開發(fā)中遇到一個(gè)問題,就是很常見的一種情況,定義一個(gè)數(shù)據(jù)的集合List,然后獲取到數(shù)據(jù)(網(wǎng)絡(luò)或者本地)之后更改List,然后通過RecycerView進(jìn)行展示,這時(shí)候我們通常使用Adapter的notifyDataSetChanged()方法來刷新,但是卻無效。
下面我大概模擬一下:
private List<Test> mList = new ArrayList<>(); // 定義數(shù)據(jù)源集合
// 獲取到數(shù)據(jù)進(jìn)行更新
private void updateData(List<Test> list) {
mList = list;
mAdapter.notifyDataSetChanged(); //刷新
}
mList為綁定Adapter的數(shù)據(jù)源,然后通過updateData()獲取到新數(shù)據(jù),然后通過 notifyDataSetChanged()進(jìn)行刷新,然后發(fā)現(xiàn)并沒有任何效果。
分析
其實(shí)這是一個(gè)很容易犯的錯(cuò)誤,代碼很簡(jiǎn)單,但就是沒效果。原因就出在mAdater前后使用的不是一個(gè)對(duì)象。雖然上面的例子使用的都為mList,看似沒有變,實(shí)際上在更新數(shù)據(jù)的時(shí)候,直接把返回?cái)?shù)據(jù)的集合賦值給了mList。難道賦值后就不是同一個(gè)集合對(duì)象了?
如何證明是不是一個(gè)對(duì)象呢?這里運(yùn)用到了Java的基礎(chǔ)知識(shí),我們?cè)诟聰?shù)據(jù)前和更新數(shù)據(jù)后打印mList的內(nèi)存地址(System.identityHashCode(mList))值來驗(yàn)證一下:
/com.xxx.test E/tag: 250846535
/com.xxx.test E/tag: 59754868
發(fā)現(xiàn)前后打印的兩個(gè)值并不相同,證明不是一個(gè)對(duì)象。這就是導(dǎo)致調(diào)用Adapter的notifyDataSetChanged()方法不起作用的根本原因。
補(bǔ)充:
1、Java中是沒有直接獲取內(nèi)存地址的方法,上面的值是通過
System.identityHashCode(mList)得來的。這個(gè)值是通過對(duì)象的內(nèi)存地址算出來的,所以可以間接的認(rèn)為是內(nèi)存地址,所以只要是同一個(gè)對(duì)象的話,那么System.identityHashCode(object)值是不變的。
2、System.identityHashCode(object)與object.hashCode()的區(qū)別:前者的話由于是根據(jù)內(nèi)存地址算出來的,所以是唯一的,只要這個(gè)值相等,就可以認(rèn)為是同一個(gè)對(duì)象。而后者這個(gè)方法是可以重寫的,例如String、List都將這個(gè)方法重寫了,所以可能得到的hashCode相同,但實(shí)際卻是不同的對(duì)象。
解決
既然我們發(fā)現(xiàn)使用的不是一個(gè)對(duì)象,那這就簡(jiǎn)單了,修改如下:
// 獲取到數(shù)據(jù)進(jìn)行更新
private void updateData(List<String> list) {
mList.clear();
mList.addAll(list);
mAdapter.notifyDataSetChanged(); //刷新
}
代碼很簡(jiǎn)單,這樣就保證了更新數(shù)據(jù)前后,mList始終為同一個(gè)對(duì)象。我們繼續(xù)通過打印內(nèi)存地址驗(yàn)證一下:
/com.xxx.test E/tag: 250846535
/com.xxx.test E/tag: 250846535
發(fā)現(xiàn)內(nèi)存地址一致,大功告成~
總結(jié)
- 通過
System.identityHashCode(object)方法來間接的獲取內(nèi)存地址; - 創(chuàng)建出來的對(duì)象,只要沒被銷毀,內(nèi)存地址始終不變。
-
Adapter綁定的數(shù)據(jù)源集合要為同一個(gè)集合,notifyDataSetChanged()方法才有效,否則需要重新設(shè)置數(shù)據(jù)源。
歡迎各位大神批評(píng)指教,感謝~