viewPager+fragment刷新緩存fragment的方法
最近在做一個(gè)項(xiàng)目,有一個(gè)功能是答題翻頁。于是需要實(shí)現(xiàn)在這一頁的時(shí)候就緩存下一頁。
剛剛開始我是用
setOnPageChangeListener方法監(jiān)聽,滑到這一頁的時(shí)候才刷新這一頁: public void onPageSelected(int position) { ReadFragment fragment= (ReadFragment) fragmentArrayList.get(position); fragment.refresh(); }
不過這樣就只有滑動(dòng)到這一頁的時(shí)候才能用fragmentArrayList.get(position)獲取當(dāng)前頁,用這種方法獲取下一頁的fragment就會(huì)報(bào)空指針。也就是說無法先緩存刷新下一頁的內(nèi)容。
到底怎么樣才能獲取得到下一頁的fragment呢?
百度了一下好像說要在
FragmentPagerAdapter里面的instantiateItem()處理。于是我看了一下它的源代碼:
@Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }
可以看出:instantiateItem方法中并不是直接去List里面拿到Fragment,而是先從FragmentManager中通過Tag找對(duì)應(yīng)的Fragment,如果可以找到就不會(huì)去List里面拿了,介于這種情況,我在adapter中加入了這個(gè)方法:
public ReadFragment getFragment(int position) { String tag = getFragmentTag(mContainer.getId(),position); ReadFragment fragment = (ReadFragment) fm.findFragmentByTag(tag); return fragment; } /** * 運(yùn)用反射機(jī)制調(diào)用FragmentPagerAdapter的getFragmentTag的方法 * @param viewId * @param index * @return */ private String getFragmentTag(int viewId, int index) { try { Class<FragmentPagerAdapter> cls = FragmentPagerAdapter.class; Class<?>[] parameterTypes = { int.class, long.class }; Method method = cls.getDeclaredMethod("makeFragmentName", parameterTypes); method.setAccessible(true); String tag = (String) method.invoke(this, viewId, index); return tag; } catch (Exception e) { e.printStackTrace(); return ""; } }
在onPageSelected里面調(diào)用getFragment(int position)方法,達(dá)到當(dāng)選中這一頁的時(shí)候就先緩存刷新下一頁。
getFragment(int position)方法其實(shí)就是拿到緩存的fragment,不過就得先保證該fragment已經(jīng)先在viewpager中緩存了,雖然內(nèi)容還沒有刷新,這樣就不會(huì)報(bào)空指針了。
出現(xiàn)了一個(gè)問題,onPageSelected在viewPager展示第一頁的時(shí)候是不會(huì)調(diào)用的,所以第一頁的內(nèi)容還是得另外刷新,無法在onPageSelected里面刷新。
建立一個(gè)方法initData(),在里面刷新。
由于viewPager展示第一頁的時(shí)候不會(huì)調(diào)用onPageSelected,那也就導(dǎo)致了第一頁和第二頁的內(nèi)容都無法先得到緩存,所以第一頁和第二頁的內(nèi)容都得在initData里面單獨(dú)刷新,其它的通過onPageSelected里面的方法來刷新。
到了這里總結(jié)一下思路:
剛剛進(jìn)入界面的時(shí)候:刷新第一頁,緩存第二頁。
翻頁時(shí)候:從第一頁翻到第二頁,執(zhí)行onPageSelected()
onPagerSelected里面調(diào)用方法getFragment(int position),獲取到下一頁即第三頁的fragment,然后刷新緩存內(nèi)容。
從第二頁翻到第三頁:執(zhí)行onPageSelected()
onPagerSelected里面調(diào)用方法getFragment(int position),獲取到下一頁即第四頁的fragment,然后刷新緩存內(nèi)容。
結(jié)果又出現(xiàn)了又一個(gè)問題:從第一頁翻到第二頁的時(shí)候,閃退了,報(bào)空指針。
后來調(diào)試了一下發(fā)現(xiàn)getFragment方法得到的fragment為null,沒道理,為啥,想到最后才發(fā)現(xiàn)原來是因?yàn)榈谌摰膄ragment在viewPager中沒有緩存,而我們的getFragment是在緩存中通過tag標(biāo)記來拿的。
怎么才能讓第三個(gè)fragment在viewPager中實(shí)現(xiàn)得到緩存呢?
默認(rèn)的,viewpager在第一頁的時(shí)候會(huì)緩存第二頁,到了第二頁的時(shí)候會(huì)緩存第一與第二頁(這里的緩存是指組件不是指內(nèi)容都是一樣的),實(shí)踐證明,只有當(dāng)?shù)诙撏耆@示的時(shí)候,第三頁才會(huì)得到緩存,而onPagerSelected在fragment滑到超過屏幕一半而且我們手指放開了才會(huì)調(diào)用,如果我們的手指沒有放開是不會(huì)被調(diào)用的,當(dāng)我們的手指放開,onPagerSelected被調(diào)用的時(shí)候,第三頁還沒有得到緩存。
怎么辦,我又想到了
@Override public void onPageScrollStateChanged(int state) {}
本認(rèn)為可以在里面判斷state==2,即滑動(dòng)停止的時(shí)候,才緩存刷新這一頁,最后才發(fā)現(xiàn)一樣問題
原來滑動(dòng)停止指的是手指的滑動(dòng),即手指離開屏幕,而不是指改fragment的滑動(dòng)。
怎么辦,不用怕:還有一個(gè)方法:readViewPager.setOffscreenPageLimit(2);
該方法可以給你答案。
這個(gè)方法可以設(shè)置viewPager當(dāng)前頁兩邊的緩存數(shù)目,readViewPager.setOffscreenPageLimit(2);當(dāng)前頁左右各緩存2個(gè)。viewPager默認(rèn)的是readViewPager.setOffscreenPageLimit(1);
這樣就OK了?,高興太早了?;降谖屙摰臅r(shí)候出問題了,是空白的。改為readViewPager.setOffscreenPageLimit(3);也一樣。
(此時(shí)我總共只有4個(gè)fragment,我采用的是無限循環(huán)模式,實(shí)際的fragment有4個(gè))而實(shí)際緩存的有5個(gè)fragment(當(dāng)前頁加左右兩個(gè)),會(huì)不會(huì)是這里出問題。
于是我把fragment改為5個(gè),結(jié)果沒問題了。
但是往回翻頁的時(shí)候出問題了,翻幾頁后又出現(xiàn)了空白頁,于是我改為6個(gè)fragment,才完全沒問題。暈。
還有往回翻頁也需要刷新緩存內(nèi)容。
以上所述是小編給大家介紹的viewPager+fragment刷新緩存fragment的方法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android中ViewPager獲取當(dāng)前顯示的Fragment
- ViewPager 與 Fragment相結(jié)合實(shí)現(xiàn)微信界面實(shí)例代碼
- Android 開發(fā)之BottomBar+ViewPager+Fragment實(shí)現(xiàn)炫酷的底部導(dǎo)航效果
- Android App中ViewPager與Fragment結(jié)合的一些問題解決
- Android App在ViewPager中使用Fragment的實(shí)例講解
- Android App中使用ViewPager+Fragment實(shí)現(xiàn)滑動(dòng)切換效果
相關(guān)文章
詳解Android中通過Intent類實(shí)現(xiàn)組件間調(diào)用的方法
Intent能夠?qū)崿F(xiàn)應(yīng)用間的數(shù)據(jù)交互與通訊,將實(shí)現(xiàn)者和調(diào)用者解耦,接下來就來詳解Android中通過Intent類實(shí)現(xiàn)組件間調(diào)用的方法,需要的朋友可以參考下2016-05-05Android實(shí)現(xiàn)文件存儲(chǔ)案例
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)文件存儲(chǔ)案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Android應(yīng)用中ListView利用OnScrollListener分頁加載數(shù)據(jù)
這篇文章主要介紹了Android應(yīng)用中ListView利用OnScrollListener分頁加載數(shù)據(jù)的方法,包括對(duì)OnScrollListener事件順序次數(shù)的分析,需要的朋友可以參考下2016-03-03Android實(shí)現(xiàn)自動(dòng)點(diǎn)擊無障礙服務(wù)功能的實(shí)例代碼
這篇文章主要介紹了Android實(shí)現(xiàn)自動(dòng)點(diǎn)擊無障礙服務(wù)功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Android getJSONObject與optJSONObject的區(qū)別結(jié)合源碼分析
這篇文章主要介紹了Android getJSONObject與optJSONObject的區(qū)別,結(jié)合源碼分析的相關(guān)資料,需要的朋友可以參考下2017-02-02Android App啟動(dòng)圖啟動(dòng)界面(Splash)的簡單實(shí)現(xiàn)代碼
這篇文章主要介紹了Android App啟動(dòng)圖啟動(dòng)界面(Splash)的簡單實(shí)現(xiàn)代碼,本文通過實(shí)例圖文詳解相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Android實(shí)現(xiàn)webview實(shí)例代碼
本篇文章主要介紹了Android實(shí)現(xiàn)webview實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06