問(wèn)題描述
最近做一個(gè)新功能,用到Viewpager內(nèi)嵌Fragment的結(jié)構(gòu),由于需要做緩存,所以每次進(jìn)入都會(huì)先根據(jù)緩存的標(biāo)簽去加載緩存數(shù)據(jù),再去服務(wù)器請(qǐng)求最新的標(biāo)簽加載最新數(shù)據(jù),這就需要刷新Viewpager中的Fragment,但是如果你只是用Adapter.notifyDataSetChanged()試圖去更新Viewpager的adapter數(shù)據(jù), 或者Viewpager.removeAllView()去刪除Viewpager中的Fragment時(shí),你會(huì)發(fā)現(xiàn)根本沒(méi)有真正刪除,因?yàn)槟銜?huì)發(fā)現(xiàn)Fragment中的數(shù)據(jù)并沒(méi)有被內(nèi)存釋放,刷新后的Fragment依然在用之前的Fragment內(nèi)存中的值,表現(xiàn)就是刷新數(shù)據(jù)重復(fù)。通過(guò)斷點(diǎn)調(diào)試也驗(yàn)證了這個(gè)問(wèn)題,F(xiàn)ragment中的變量在內(nèi)存中被重用了。
解決方法
一.繼承FragmentStatePagerAdapter
將Viewpager的Adapter由繼承FragmentPagerAdapter改為繼承FragmentStatePagerAdapter。
二.實(shí)現(xiàn)getItemPosition方法
@Overridepublic int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
原因
引用一下StackOverFlow上大神的解釋,解釋得非常清楚
The ViewPager doesn't remove your fragments with the code above because it loads several views (or fragments in your case) into memory. In addition to the visible view, it also loads the view to either side of the visible one. This provides the smooth scrolling from view to view that makes the ViewPager so cool.
To achieve the effect you want, you need to do a couple of things.
Change the FragmentPagerAdapter to a FragmentStatePagerAdapter. The reason for this is that the FragmentPagerAdapter will keep all the views that it loads into memory forever. Where the FragmentStatePagerAdapter disposes of views that fall outside the current and traversable views.
Override the adapter method getItemPosition (shown below). When we callmAdapter.notifyDataSetChanged(); the ViewPager interrogates the adapter to determine what has changed in terms of positioning. We use this method to say that everything has changed so reprocess all your view positioning。
大致意思如下:
Viewpgaer不會(huì)刪除Fragment是因?yàn)樗鼤?huì)加載多個(gè)View或者Fragment到內(nèi)存,對(duì)于可見(jiàn)的View,它還會(huì)加載左右的View,這樣才能保證滑動(dòng)流暢。
一.首先需要繼承FragmentStatePagerAdapter,因?yàn)镕ragmentPagerAdapter會(huì)永久保存所有加載的View到內(nèi)存,這時(shí)你做任何刪除操作都是無(wú)用的,但是FragmentStatePagerAdapter不會(huì)。
二.當(dāng)我們用Viewpager的Adapter.notifyDataSetChanged()的時(shí)候,Viewpgaer會(huì)去查詢到底哪個(gè)位置有改變,當(dāng)我們視線了getItemPosition的如上方法,就是告訴所有的View都已經(jīng)變化,從而達(dá)到刷新的目的。