RecyclerView遇到notifyDataSetChanged無效時的解決方案

作者簡介? 創(chuàng)微信公眾號郭霖 WeChat ID: guolin_blog

本篇來自CSDN_LQR的投稿,分析了Fragment中使用RecyclerView時notifyDataSetChanged可能出現(xiàn)的問題,希望能夠幫助到大家。

CSDN_LQR的博客地址:

http://www.itdecent.cn/u/f9de259236a3

簡述

不管 AbsListView(ListView、GridView) 或是 新出的RecyclerView,在使用 notifyDataSetChanged方法 更新列表數(shù)據(jù)時,一定要保證數(shù)據(jù)為同個對象(即hashCode要一致)。對于這個問題的論證,可以去看官方源代碼,或是看我之前寫的一篇博文

解決ListViews適配器notifyDataSetChanged()無效問題

http://blog.csdn.net/csdn_lqr/article/details/50947825

相信可以幫到你。但是,這個不是本文的重點(diǎn),本文重點(diǎn)講解在 Fragment 中,RecyclerView 遇到 notifyDataSetChanged 無效的問題。如果你趕時間,可以直接看第三部分("總結(jié)")。

探索

1、查看數(shù)據(jù)(mData)是否是同個對象

tip:java中可以通過打印 hashCode 的方式判斷 mData 是否為同個對象。

注意:initData方法 在 onActivityCreated() 中被調(diào)用。


2、操作與結(jié)果

tip:常規(guī)對 Fragment 的使用,會對其進(jìn)行緩存,也可能使用單例模式,反正就是短時間內(nèi)不會重新創(chuàng)建。

①操作一

打開 Activity 后,切換 Fragment(第一次初始化 Fragment)。顯示效果如下:


②操作二

切換別的 Fragment 后,再切回剛才的 Fragment(此前該 Fragment 已經(jīng)在存在,所以不會再次創(chuàng)建)。顯示效果如下:


③看控制臺


可以看到數(shù)據(jù)對象地址一樣,即為同一個。

3、查看RecyclerView是否是同個對象

說實(shí)話,這個是踩坑經(jīng)驗(yàn)豐富的網(wǎng)友在群里說的,如果不是他說出來,打死我也沒想到,居然還有這么一個坑。從上面的結(jié)果可以看出,adapter 中是有數(shù)據(jù)的沒錯,而且數(shù)據(jù)地址沒變,所以理應(yīng) notifyDataSetChanged()方法 會生效。但是為什么會這樣呢,這里先賣個關(guān)子,先看下面的操作。

①改下上面的代碼,打印RecyclerView的地址

代碼如下:


②同上述操作一致

對同一個 Fragment 來回切換,看控制臺輸出。


果然不一樣?。?!

總結(jié)

為什么在 Fragment 中 RecyclerView 的地址會發(fā)生變化呢?我們先理清一下 Fragment 生命周期會陸續(xù)調(diào)用的幾個方法:

onCreate()->onCreateView()->onActivityCreated()->onDestroy()

中間少了幾個方法,請不用在意,下面貼下我的 BaseFragment 代碼:


當(dāng)一個 Fragment 在來回切換時,分別調(diào)用的方法如下:

第一次顯示:

onCreate()->onCreateView()->onActivityCreated()

第二次顯示:

onCreateView()->onActivityCreated()

這里不難理解,因?yàn)?Fragment 一般使用的時候會被緩存,所以,當(dāng)?shù)诙物@示的時候,不會調(diào)用 onCreate()。只會調(diào)用 onCreateView() 和 onActivityCreated(),這也就是 RecyclerView 地址不一樣的原因所在,因?yàn)榭丶@取操作是在 initView() 中進(jìn)行的,即 RecyclerView 的獲取操作在 onCreateView() 中,而 Fragment 的每次顯示都會調(diào)用 onCreateView(),所以 RecyclerView 控件會被再次獲取,即重新創(chuàng)建一個對象(此時hashCode就變化了)。

結(jié)論

所以,在 Fragment 中使用 RecyclerView 或 AbsListView 控件的 notifyDataSetChanged()方法 時,除了保證數(shù)據(jù)(mData對象)不能變以外,控件本身一樣也不能變。

解決方案

因?yàn)?Fragment 的 onCreateView() 和 onActivityCreated() 方法在每次 Fragment 顯示的時候會被調(diào)用,控件會被重新創(chuàng)建一次,所以,解決方法只能是在這兩個方法中重新對RecyclerView 設(shè)置適配器,而不要使用 notifyDataSetChanged(),故代碼改為如下:


注:只是建議不要在上述兩個生命周期方法中使用 notifyDataSetChanged() 而已,只要在保證 RecyclerView 等列表控件設(shè)置完適配器后,可以在任意地方繼續(xù)使用 notifyDataSetChanged()。


文章原創(chuàng)作者GuoLin 書籍推薦

郭林大神原創(chuàng)android 書籍:《第一行代碼 android》

淘寶鏈接: https://s.click.taobao.com/t?e=m%3D2%26s%3DgKUfuKdAZKocQipKwQzePOeEDrYVVa64K7Vc7tFgwiHjf2vlNIV67p2n%2BQBNMyE6Rku8%2Bpj6eJall3bs%2B3NRhNHnsKI%2BqxhyM0iVZhTFBom4YIorMPnmg8G0g2OJi%2FzmXHfenomYtn5EW9vzeG8LzfPUwktUBEmkxg5p7bh%2BFbQ%3D&pvid=10_106.6.161.154_3367_1490163222155

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容