安卓開發(fā)之FragmentPagerAdapter和FragmentStatePagerAdapter詳解
最近遇到比較奇怪的bug,TableLayout+ViewPager實現(xiàn)點擊頂部tab切換viewpager視圖。但是在Viewpager設置dapter時,最開始設置的是FragmentPagerAdapter,會導致tab切換后FragmentPagerAdapter內(nèi)的視圖未刷新(與上一個tab內(nèi)容重復或展示成空白,展示成空白一般出現(xiàn)在頁面重啟后不能完成刷新成功)。替換成FragmentStatePagerAdapter或者FragmentStateAdapter,便解決了這一問題。這其實是個比較常見的bug,網(wǎng)絡上有很多推薦的解決方案。那么到底FragmentPagerAdapter、FragmentStateAdapter以及FragmentStatePagerAdapter有何具體的區(qū)別呢?在這篇文章中我將詳細解答。
根據(jù)類圖進行分析
FragmentPagerAdapter與FragmentPagerStateAdapter區(qū)別點:
一:二者在狀態(tài)保存有差異:FragmentPagerAdapter并未實現(xiàn)saveState()、restoreState()
public class FragmentPagerAdapter{ ? ? // ...... ? ? public static final int POSITION_UNCHANGED = -1; ? ? public static final int POSITION_NONE = -2; ? ? ? public Parcelable saveState() { ? ? ? ? return null; ? ? } ? ? ? public void restoreState(Parcelable state, ClassLoader loader) { ? ? ? ?? ? ? } }
而FragmentPagerStateAdapter則實現(xiàn)了saveState()、restoreState()這倆方法:
?public Parcelable saveState() { ? ? ? ? Bundle state = null; ? ? ? ? if (mSavedState.size() > 0) { ? ? ? ? ? ? state = new Bundle(); ? ? ? ? ? ? Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()]; ? ? ? ? ? ? mSavedState.toArray(fss); ? ? ? ? ? ? state.putParcelableArray("states", fss); ? ? ? ? } ? ? ? ? for (int i=0; i<mFragments.size(); i++) { ? ? ? ? ? ? Fragment f = mFragments.get(i); ? ? ? ? ? ? if (f != null && f.isAdded()) { ? ? ? ? ? ? ? ? if (state == null) { ? ? ? ? ? ? ? ? ? ? state = new Bundle(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? String key = "f" + i; ? ? ? ? ? ? ? ? mFragmentManager.putFragment(state, key, f); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return state; ? ? } ? ? ? @Override ? ? public void restoreState(Parcelable state, ClassLoader loader) { ? ? ? ? if (state != null) { ? ? ? ? ? ? Bundle bundle = (Bundle)state; ? ? ? ? ? ? bundle.setClassLoader(loader); ? ? ? ? ? ? Parcelable[] fss = bundle.getParcelableArray("states"); ? ? ? ? ? ? mSavedState.clear(); ? ? ? ? ? ? mFragments.clear(); ? ? ? ? ? ? if (fss != null) { ? ? ? ? ? ? ? ? for (int i=0; i<fss.length; i++) { ? ? ? ? ? ? ? ? ? ? mSavedState.add((Fragment.SavedState)fss[i]); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? Iterable<String> keys = bundle.keySet(); ? ? ? ? ? ? for (String key: keys) { ? ? ? ? ? ? ? ? if (key.startsWith("f")) { ? ? ? ? ? ? ? ? ? ? int index = Integer.parseInt(key.substring(1)); ? ? ? ? ? ? ? ? ? ? Fragment f = mFragmentManager.getFragment(bundle, key); ? ? ? ? ? ? ? ? ? ? if (f != null) { ? ? ? ? ? ? ? ? ? ? ? ? while (mFragments.size() <= index) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? mFragments.add(null); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? f.setMenuVisibility(false); ? ? ? ? ? ? ? ? ? ? ? ? mFragments.set(index, f); ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? Log.w(TAG, "Bad fragment at key " + key); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? }
FragmentStatePagerAdapter對Fragment的狀態(tài)進行了保存
二:二者在視圖管理方法差異:
FragmentStatePagerAdapter是整個Fragment對象的移除和重建
?public Object instantiateItem(ViewGroup container, int position) { ? ? ? ? if (mFragments.size() > position) { ? ? ? ? ? ? Fragment f = mFragments.get(position); ? ? ? ? ? ? if (f != null) { ? ? ? ? ? ? ? ? return f; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? ? if (mCurTransaction == null) { ? ? ? ? ? ? mCurTransaction = mFragmentManager.beginTransaction(); ? ? ? ? } ? ? ? ? ? // 實例化fragment(交給我們實現(xiàn)的getItem方法) ? ? ? ? Fragment fragment = getItem(position); ? ? ? ? ? if (mSavedState.size() > position) { ? ? ? ? ? ? Fragment.SavedState fss = mSavedState.get(position); ? ? ? ? ? ? if (fss != null) { ? ? ? ? ? ? ? ? fragment.setInitialSavedState(fss); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? // 如果緩存 <= ViewPager傳入的position,說明當前位置還未存入緩存. ? ? ? ? while (mFragments.size() <= position) { ? ? ? ? ? ? // 先占個坑 ? ? ? ? ? ? mFragments.add(null); ? ? ? ? } ? ? ? ? fragment.setUserVisibleHint(false); ? ? ? ? // 填坑 ? ? ? ? mFragments.set(position, fragment); ? ? ? ? // 填充視圖 ? ? ? ? mCurTransaction.add(container.getId(), fragment); ? ? ? ? return fragment; ? ? } ? ? ? @Override ? ? public void destroyItem(ViewGroup container, int position, Object object) { ? ? ? ? Fragment fragment = (Fragment) object; ? ? ? ? ? if (mCurTransaction == null) { ? ? ? ? ? ? mCurTransaction = mFragmentManager.beginTransaction(); ? ? ? ? } ? ? ? ? // 從緩存中移除 ? ? ? ? mFragments.set(position, null); ? ? ? ? // 從FragmentManager中移除 ? ? ? ? mCurTransaction.remove(fragment); ? ? }
FragmentPagerAdapter是視圖的attach和detach,不會對整個fragment進行完全的添加和刪除操作。
因此,可見二者在使用場景上不同,如果頁面較少,仍舊希望能夠?qū)⑸傻腇ragment保存在內(nèi)存中,在需要顯示的時候直接調(diào)用。而不要產(chǎn)生生成、銷毀對象的額外開銷。這樣效率最高。這種情況下,選中FragmentPagerAdapter更合適。
對于在使用FragmentPagerAdapter出現(xiàn)白屏或者刷新不了的bug,除了替換成FragmentStatePagerAdapter,還需要重載getItem()和instantiateItem()對象。
對于getItemPosition()方法,兩個累的區(qū)別是:FragmentStatePagerAdapter會在因POSITION_NONE觸發(fā)調(diào)用的destroyItem中真正的釋放資源,重新建立一個新的Fragment;而FragmentPagerAdapter僅僅會在destoryItem()中detach這個Fragment,在instantiateItem()時會使用舊的Fragment,并觸發(fā)attach,并沒有觸發(fā)資源及重建的過程。
到此這篇關于安卓開發(fā)之FragmentPagerAdapter和FragmentStatePagerAdapter詳解的文章就介紹到這了,更多相關FragmentPagerAdapter和FragmentStatePagerAdapter詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Android基礎之使用Fragment控制切換多個頁面
- Android基礎之Fragment與Activity交互詳解
- Android中fragment嵌套fragment問題解決方法
- Android程序開發(fā)之Fragment實現(xiàn)底部導航欄實例代碼
- Android的Fragment的生命周期各狀態(tài)和回調(diào)函數(shù)使用
- Android Fragment 基本了解(圖文介紹)
- Android fragment實現(xiàn)多個頁面切換效果
- Android 管理Activity中的fragments
- Fragment里添加ListView不要用ListFragment
- FrameLayout和Fragment處理Android應用UI布局實例
相關文章
Android WebView自定義長按選擇實現(xiàn)收藏/分享選中文本功能
這篇文章主要介紹了Android WebView自定義長按選擇實現(xiàn)收藏/分享選中文本功能,需要的朋友可以參考下2017-06-06教你制作Android中炫酷的ViewPagerIndicator(不僅仿MIUI)
ViewPagerIndicator作為一款分頁指標小部件兼容ViewPager,封裝上做得非常不錯,目前已為眾多知名應用所使用。今天給你大家分享一個炫酷的效果,有需要的可以參考學習。2016-08-08Android同步異步任務與多線程及Handler消息處理機制基礎詳細講解
這篇文章主要介紹了Android同步異步任務與多線程及Handler消息處理機制基礎,handler其實就是主線程在起了一個子線程,子線程運行并生成Message,Looper獲取message并傳遞給Handler,Handler逐個獲取子線程中的Message,感興趣的小伙伴快跟隨小編一起學習一下2022-11-11詳解Android USB轉(zhuǎn)串口通信開發(fā)基本流程
本篇文章主要介紹了Android USB轉(zhuǎn)串口通信開發(fā)基本流程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04Android 3D旋轉(zhuǎn)動畫效果實現(xiàn)分解
如何實現(xiàn)View的3D旋轉(zhuǎn)效果,實現(xiàn)的主要原理就是圍繞Y軸旋轉(zhuǎn),同時在Z軸方面上有一個深入的縮放,具體實現(xiàn)代碼如下,感興趣的朋友可以參考下哈2013-06-06android針對json數(shù)據(jù)解析方法實例分析
這篇文章主要介紹了android針對json數(shù)據(jù)解析方法,以實例形式較為詳細的分析了Android操作json格式數(shù)據(jù)的各種常用技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10