作者簡(jiǎn)介? 創(chuàng)微信公眾號(hào)郭霖 WeChat ID: guolin_blog
本篇來(lái)自CSDN_LQR的投稿珊随,分析了Fragment中使用RecyclerView時(shí)notifyDataSetChanged可能出現(xiàn)的問(wèn)題粘室,希望能夠幫助到大家倾鲫。
CSDN_LQR的博客地址:
http://www.reibang.com/u/f9de259236a3
簡(jiǎn)述
不管 AbsListView(ListView遣鼓、GridView) 或是 新出的RecyclerView,在使用 notifyDataSetChanged方法 更新列表數(shù)據(jù)時(shí)酸役,一定要保證數(shù)據(jù)為同個(gè)對(duì)象(即hashCode要一致)栗竖。對(duì)于這個(gè)問(wèn)題的論證癣漆,可以去看官方源代碼维咸,或是看我之前寫的一篇博文
解決ListViews適配器notifyDataSetChanged()無(wú)效問(wèn)題
http://blog.csdn.net/csdn_lqr/article/details/50947825
相信可以幫到你。但是惠爽,這個(gè)不是本文的重點(diǎn)癌蓖,本文重點(diǎn)講解在 Fragment 中,RecyclerView 遇到 notifyDataSetChanged 無(wú)效的問(wèn)題婚肆。如果你趕時(shí)間租副,可以直接看第三部分("總結(jié)")。
探索
1较性、查看數(shù)據(jù)(mData)是否是同個(gè)對(duì)象
tip:java中可以通過(guò)打印 hashCode 的方式判斷 mData 是否為同個(gè)對(duì)象用僧。
注意:initData方法 在 onActivityCreated() 中被調(diào)用。
2赞咙、操作與結(jié)果
tip:常規(guī)對(duì) Fragment 的使用责循,會(huì)對(duì)其進(jìn)行緩存,也可能使用單例模式攀操,反正就是短時(shí)間內(nèi)不會(huì)重新創(chuàng)建院仿。
①操作一
打開(kāi) Activity 后,切換 Fragment(第一次初始化 Fragment)崔赌。顯示效果如下:
②操作二
切換別的 Fragment 后意蛀,再切回剛才的 Fragment(此前該 Fragment 已經(jīng)在存在,所以不會(huì)再次創(chuàng)建)健芭。顯示效果如下:
③看控制臺(tái)
可以看到數(shù)據(jù)對(duì)象地址一樣县钥,即為同一個(gè)。
3慈迈、查看RecyclerView是否是同個(gè)對(duì)象
說(shuō)實(shí)話若贮,這個(gè)是踩坑經(jīng)驗(yàn)豐富的網(wǎng)友在群里說(shuō)的,如果不是他說(shuō)出來(lái)痒留,打死我也沒(méi)想到谴麦,居然還有這么一個(gè)坑。從上面的結(jié)果可以看出伸头,adapter 中是有數(shù)據(jù)的沒(méi)錯(cuò)匾效,而且數(shù)據(jù)地址沒(méi)變,所以理應(yīng) notifyDataSetChanged()方法 會(huì)生效恤磷。但是為什么會(huì)這樣呢面哼,這里先賣個(gè)關(guān)子野宜,先看下面的操作。
①改下上面的代碼魔策,打印RecyclerView的地址
代碼如下:
②同上述操作一致
對(duì)同一個(gè) Fragment 來(lái)回切換匈子,看控制臺(tái)輸出。
果然不一樣4程弧;⒍亍!
總結(jié)
為什么在 Fragment 中 RecyclerView 的地址會(huì)發(fā)生變化呢政敢?我們先理清一下 Fragment 生命周期會(huì)陸續(xù)調(diào)用的幾個(gè)方法:
onCreate()->onCreateView()->onActivityCreated()->onDestroy()
中間少了幾個(gè)方法其徙,請(qǐng)不用在意,下面貼下我的 BaseFragment 代碼:
當(dāng)一個(gè) Fragment 在來(lái)回切換時(shí)堕仔,分別調(diào)用的方法如下:
第一次顯示:
onCreate()->onCreateView()->onActivityCreated()
第二次顯示:
onCreateView()->onActivityCreated()
這里不難理解擂橘,因?yàn)?Fragment 一般使用的時(shí)候會(huì)被緩存,所以摩骨,當(dāng)?shù)诙物@示的時(shí)候通贞,不會(huì)調(diào)用 onCreate()。只會(huì)調(diào)用 onCreateView() 和 onActivityCreated()恼五,這也就是 RecyclerView 地址不一樣的原因所在昌罩,因?yàn)榭丶@取操作是在 initView() 中進(jìn)行的,即 RecyclerView 的獲取操作在 onCreateView() 中灾馒,而 Fragment 的每次顯示都會(huì)調(diào)用 onCreateView()茎用,所以 RecyclerView 控件會(huì)被再次獲取,即重新創(chuàng)建一個(gè)對(duì)象(此時(shí)hashCode就變化了)睬罗。
結(jié)論
所以轨功,在 Fragment 中使用 RecyclerView 或 AbsListView 控件的 notifyDataSetChanged()方法 時(shí),除了保證數(shù)據(jù)(mData對(duì)象)不能變以外容达,控件本身一樣也不能變古涧。
解決方案
因?yàn)?Fragment 的 onCreateView() 和 onActivityCreated() 方法在每次 Fragment 顯示的時(shí)候會(huì)被調(diào)用,控件會(huì)被重新創(chuàng)建一次花盐,所以羡滑,解決方法只能是在這兩個(gè)方法中重新對(duì)RecyclerView 設(shè)置適配器,而不要使用 notifyDataSetChanged()算芯,故代碼改為如下:
注:只是建議不要在上述兩個(gè)生命周期方法中使用 notifyDataSetChanged() 而已柒昏,只要在保證 RecyclerView 等列表控件設(shè)置完適配器后,可以在任意地方繼續(xù)使用 notifyDataSetChanged()熙揍。
文章原創(chuàng)作者GuoLin 書籍推薦
郭林大神原創(chuàng)android 書籍:《第一行代碼 android》