寫文章注冊登錄首頁下載App
作者 YoKey 關(guān)注2016.02.27 21:48 字?jǐn)?shù) 3995 閱讀 44322評論 120喜歡 419http://www.jianshu.com/p/d9143a92ad94
Fragment系列文章:1、Fragment全解析系列(一):那些年踩過的坑2、Fragment全解析系列(二):正確的使用姿勢3、Fragment之我的解決方案:Fragmentation
本篇主要介紹一些最常見的Fragment的坑以及官方Fragment庫的那些自身的BUG,并給出解決方案;這些BUG在你深度使用時會遇到,比如Fragment嵌套時或者單Activity+多Fragment架構(gòu)時遇到的坑。
Fragment是可以讓你的app縱享絲滑的設(shè)計,如果你的app想在現(xiàn)在基礎(chǔ)上性能大幅度提高,并且占用內(nèi)存降低,同樣的界面Activity占用內(nèi)存比Fragment要多,響應(yīng)速度Fragment比Activty在中低端手機上快了很多,甚至能達到好幾倍!如果你的app當(dāng)前或以后有移植平板等平臺時,可以讓你節(jié)省大量時間和精力。
簡陋的目錄1、getActivity()空指針2、異常:Can not perform this action after onSaveInstanceState3、Fragment重疊異常-----正確使用hide、show的姿勢4、Fragment嵌套的那些坑5、未必靠譜的出棧方法remove()6、多個Fragment同時出棧的深坑BUG7、深坑 Fragment轉(zhuǎn)場動畫
最新版知乎,單Activity多Fragment的架構(gòu),響應(yīng)可以說非常“絲滑”,非要說缺點的話,就是沒有轉(zhuǎn)場動畫,并且轉(zhuǎn)場會有類似閃屏現(xiàn)象。我猜測可能和Fragment轉(zhuǎn)場動畫的一些BUG有關(guān)。(這系列的最后一篇文章我會給出我的解決方案,可以自定義轉(zhuǎn)場動畫,并能在各種特殊情況下正常運行。)
但是!Fragment相比較Activity要難用很多,在多Fragment以及嵌套Fragment的情況下更是如此。更重要的是Fragment的坑真的太多了,看Square公司的這篇文章吧,Square:從今天開始拋棄Fragment吧!
當(dāng)然,不能說不再用Fragment,F(xiàn)ragment的這些坑都是有解決辦法的,官方也在逐步修復(fù)一些BUG。下面羅列一些,有常見的,也有極度隱蔽的一些坑,也是我在用單Activity多Fragment時遇到的坑,可能有更多坑可以挖掘...
在這之前為了方便后面文章的介紹,先規(guī)定一個“術(shù)語”,安卓app有一種特殊情況,就是 app運行在后臺的時候,系統(tǒng)資源緊張的時候?qū)е掳補pp的資源全部回收(殺死app的進程),這時把app再從后臺返回到前臺時,app會重啟。這種情況下文簡稱為:“內(nèi)存重啟”。(屏幕旋轉(zhuǎn)等配置變化也會造成當(dāng)前Activity重啟,本質(zhì)與“內(nèi)存重啟”類似)
在系統(tǒng)要把app回收之前,系統(tǒng)會把Activity的狀態(tài)保存下來,Activity的FragmentManager負責(zé)把Activity中的Fragment保存起來。在“內(nèi)存重啟”后,Activity的恢復(fù)是從棧頂逐步恢復(fù),F(xiàn)ragment會在宿主Activity的onCreate方法調(diào)用后緊接著恢復(fù)(從onAttach生命周期開始)。
可能你遇到過getActivity()返回null,或者平時運行完好的代碼,在“內(nèi)存重啟”之后,調(diào)用getActivity()的地方卻返回null,報了空指針異常。
大多數(shù)情況下的原因:你在調(diào)用了getActivity()時,當(dāng)前的Fragment已經(jīng)onDetach()了宿主Activity。比如:你在pop了Fragment之后,該Fragment的異步任務(wù)仍然在執(zhí)行,并且在執(zhí)行完成后調(diào)用了getActivity()方法,這樣就會空指針。
解決辦法:更"安全"的方法:(對于Fragment已經(jīng)onDetach這種情況,我們應(yīng)該避免在這之后再去調(diào)用宿主Activity對象,比如取消這些異步任務(wù),但我們的團隊可能會有粗心大意的情況,所以下面給出的這個方案會保證安全)
在Fragment基類里設(shè)置一個Activity mActivity的全局變量,在onAttach(Activity activity)里賦值,使用mActivity代替getActivity(),保證Fragment即使在onDetach后,仍持有Activity的引用(有引起內(nèi)存泄露的風(fēng)險,但是異步任務(wù)沒停止的情況下,本身就可能已內(nèi)存泄漏,相比Crash,這種做法“安全”些),即:
有很多小伙伴遇到這個異常,這個異常產(chǎn)生的原因是:
在你離開當(dāng)前Activity等情況下,系統(tǒng)會調(diào)用onSaveInstanceState()幫你保存當(dāng)前Activity的狀態(tài)、數(shù)據(jù)等,直到再回到該Activity之前(onResume()之前),你使用commit()提交了Fragment事務(wù),就會拋出該異常!
解決方法2個:1、(不推薦)該事務(wù)使用commitAllowingStateLoss()方法提交,但是有可能導(dǎo)致該次提交無效!(在此次離開時恰巧Activity被強殺時)2、(推薦)在重新回到該Activity的時候(onResumeFragments()或onPostResume()),再執(zhí)行該事務(wù)!
如果你add()了幾個Fragment,使用show()、hide()方法控制,比如微信、QQ的底部tab等情景,如果你什么都不做的話,在“內(nèi)存重啟”后回到前臺,app的這幾個Fragment界面會重疊。
原因是FragmentManager幫我們管理Fragment,當(dāng)發(fā)生“內(nèi)存重啟”,他會從棧底向棧頂?shù)捻樞蛞淮涡曰謴?fù)Fragment;但是因為沒有保存Fragment的mHidden屬性,默認(rèn)為false,即show狀態(tài),所以所有Fragment都是以show的形式恢復(fù),我們看到了界面重疊。(如果是replace,恢復(fù)形式和Activity一致,只有當(dāng)你pop之后上一個Fragment才開始重新恢復(fù),所有使用replace不會造成重疊現(xiàn)象)
還有一種場景,add和replace都有可能造成重疊: 在onCreate中加載Fragment,并且沒有判斷saveInstanceState==null,導(dǎo)致重復(fù)加載了同一個Fragment導(dǎo)致重疊。(PS:replace情況下,如果沒有加入回退棧,則不判斷也不會造成重疊,但建議還是統(tǒng)一判斷下)
詳細原因:從源碼角度分析,為什么會發(fā)生Fragment重疊?
這里給出3個解決方案:1、是大家比較熟悉的 findFragmentByTag:
即在add()或者replace()時綁定一個tag,一般我們是用fragment的類名作為tag,然后在發(fā)生“內(nèi)存重啟”時,通過findFragmentByTag找到對應(yīng)的Fragment,并hide()需要隱藏的fragment。
下面是個標(biāo)準(zhǔn)恢復(fù)寫法:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity); TargetFragment targetFragment; HideFragment hideFragment; if (savedInstanceState != null) { // “內(nèi)存重啟”時調(diào)用 targetFragment = getSupportFragmentManager().findFragmentByTag(TargetFragment.class.getName); hideFragment = getSupportFragmentManager().findFragmentByTag(HideFragment.class.getName); // 解決重疊問題 getFragmentManager().beginTransaction() .show(targetFragment) .hide(hideFragment) .commit(); }else{ // 正常時 targetFragment = TargetFragment.newInstance(); hideFragment = HideFragment.newInstance(); getFragmentManager().beginTransaction() .add(R.id.container, targetFragment, targetFragment.getClass().getName()) .add(R.id,container,hideFragment,hideFragment.getClass().getName()) .hide(hideFragment) .commit(); }}如果你想恢復(fù)到用戶離開時的那個Fragment的界面,你還需要在onSaveInstanceState(Bundle outState)里保存離開時的那個可見的tag或下標(biāo),在onCreate“內(nèi)存重啟”代碼塊中,取出tag/下標(biāo),進行恢復(fù)。
2、使用getSupportFragmentManager().getFragments()恢復(fù)
通過getFragments()可以獲取到當(dāng)前FragmentManager管理的棧內(nèi)所有Fragment。
標(biāo)準(zhǔn)寫法如下:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity); TargetFragment targetFragment; HideFragment hideFragment; if (savedInstanceState != null) { // “內(nèi)存重啟”時調(diào)用 List<Fragment> fragmentList = getSupportFragmentManager().getFragments(); for (Fragment fragment : fragmentList) { if(fragment instanceof TartgetFragment){ targetFragment = (TargetFragment)fragment; }else if(fragment instanceof HideFragment){ hideFragment = (HideFragment)fragment; } } // 解決重疊問題 getFragmentManager().beginTransaction() .show(targetFragment) .hide(hideFragment) .commit(); }else{ // 正常時 targetFragment = TargetFragment.newInstance(); hideFragment = HideFragment.newInstance(); // 這里add時,tag可傳可不傳 getFragmentManager().beginTransaction() .add(R.id.container) .add(R.id,container,hideFragment) .hide(hideFragment) .commit(); }}從代碼看起來,這種方式比較復(fù)雜,但是這種方式在一些場景下比第一種方式更加簡便有效。我會在下一篇中介紹在不同場景下如果選擇,何時用findFragmentByTag(),何時用getFragments()恢復(fù)。
順便一提,有些小伙伴會用一種并不合適的方法恢復(fù)Fragment,雖然效果也能達到,但并不恰當(dāng)。即:
// 保存@Overrideprotected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); getSupportFragmentManager().putFragment(outState, KEY, targetFragment);}// 恢復(fù)@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scrolling); if (savedInstanceState != null) { Fragment targetFragment = getSupportFragmentManager().getFragment(savedInstanceState, KEY); }}如果僅僅為了找回棧內(nèi)的Fragment,使用putFragment(bundle, key, fragment)保存fragment,是完全沒有必要的;因為FragmentManager在任何情況都會幫你存儲Fragment,你要做的僅僅是在“內(nèi)存重啟”后,找回這些Fragment即可。。
3、我的解決方案,9行代碼解決所有情況的Fragment重疊:傳送門
其實一些小伙伴遇到的很多嵌套的坑,大部分都是由于對嵌套的棧視圖產(chǎn)生混亂,只要理清棧視圖關(guān)系,做好恢復(fù)相關(guān)工作以及正確選擇是使用getFragmentManager()還是getChildFragmentManager()就可以避免這些問題。
這部分內(nèi)容是我們感覺Fragment非常難用的一個點,我會在下一篇中,詳細介紹使用Fragment嵌套的一些技巧,以及如何清晰分析各個層級的棧視圖。
附:startActivityForResult接收返回問題在support 23.2.0以下的支持庫中,對于在嵌套子Fragment的startActivityForResult (),會發(fā)現(xiàn)無論如何都不能在onActivityResult()中接收到返回值,只有最頂層的父Fragment才能接收到,這是一個support v4庫的一個BUG,不過在前兩天發(fā)布的support 23.2.0庫中,已經(jīng)修復(fù)了該問題,嵌套的子Fragment也能正常接收到返回數(shù)據(jù)了!
如果你想讓某一個Fragment出棧,使用remove()在加入回退棧時并不靠譜。
如果你在add的同時將Fragment加入回退棧:addToBackStack(name)的情況下,它并不能真正將Fragment從棧內(nèi)移除,如果你在2秒后(確保Fragment事務(wù)已經(jīng)完成)打印getSupportFragmentManager().getFragments(),會發(fā)現(xiàn)該Fragment依然存在,并且依然可以返回到被remove的Fragment,而且是空白頁面。
如果你沒有將Fragment加入回退棧,remove方法可以正常出棧。
如果你加入了回退棧,popBackStack()系列方法才能真正出棧,這也就引入下一個深坑,popBackStack(String tag,int flags)等系列方法的BUG。
在Fragment庫中如下4個方法是有BUG的:
1、popBackStack(String tag,int flags)2、popBackStack(int id,int flags)3、popBackStackImmediate(String tag,int flags)4、popBackStackImmediate(int id,int flags)
上面4個方法作用是,出棧到tag/id的fragment,即一次多個Fragment被出棧。
1、FragmentManager棧中管理fragment下標(biāo)位置的數(shù)組ArrayList<Integer> mAvailIndeices的BUG
下面的方法FragmentManagerImpl類方法,產(chǎn)生BUG的罪魁禍?zhǔn)资枪芾鞦ragment棧下標(biāo)的mAvailIndeices屬性:
上面代碼最終導(dǎo)致了棧內(nèi)順序不正確的問題,如下圖:

上面的這個情況,會一次異常,一次正常。帶來的問題就是“內(nèi)存重啟”后,各種異常甚至Crash。
發(fā)現(xiàn)這BUG的時候,我一臉懵比,幸好,stackoverflow上有大神給出了解決方案!hack FragmentManagerImpl的mAvailIndices,對其進行一次Collections.reverSEOrder()降序排序,保證棧內(nèi)Fragment的index的正確。
使用方法就是通過popBackStackImmediate(tag/id)多個Fragment后,調(diào)用
2、popBackStack的坑popBackStack和popBackStackImmediate的區(qū)別在于前者是加入到主線隊列的末尾,等其它任務(wù)完成后才開始出棧,后者是立刻出棧。
如果你popBackStack多個Fragment后,緊接著beginTransaction() add新的一個Fragment,接著發(fā)生了“內(nèi)存重啟”后,你再執(zhí)行popBackStack(),app就會Crash,解決方案是postDelay出棧動畫時間再執(zhí)行其它事務(wù),但是根據(jù)我的觀察不是很穩(wěn)定。我的建議是:如果你想出棧多個Fragment,你應(yīng)盡量使用popBackStackImmediate(tag/id),而不是popBackStack(tag/id),如果你想在出棧后,立刻beginTransaction()開始一項事務(wù),你應(yīng)該把事務(wù)的代碼post/postDelay到主線程的消息隊列里,下一篇有詳細描述。
如果你的Fragment沒有轉(zhuǎn)場動畫,或者使用setCustomAnimations(enter, exit)的話,那么上面的那些坑解決后,你可以愉快的玩耍了。
(注意:如果你想給下一個Fragment設(shè)置進棧動畫和出棧動畫,.setCustomAnimations(enter, exit)只能設(shè)置進棧動畫,第二個參數(shù)并不是設(shè)置出棧動畫;請使用.setCustomAnimations(enter, exit, popEnter, popExit),這個方法的第1個參數(shù)對應(yīng)進棧動畫,第4個參數(shù)對應(yīng)出棧動畫,所以是.setCustomAnimations(進棧動畫, exit, popEnter, 出棧動畫))
總結(jié)起來就是Fragment沒有出棧動畫的話,可以避免很多坑。如果想讓出棧動畫運作正常的話,需要使用Fragment的onCreateAnimation中控制動畫。
但是用代價也是有的,你需要解決出棧動畫帶來的幾個坑。
1、pop多個Fragment時轉(zhuǎn)場動畫 帶來的問題在使用 pop(tag/id)出棧多個Fragment的這種情況下,將轉(zhuǎn)場動畫臨時取消或者延遲一個動畫的時間再去執(zhí)行其他事務(wù);
原因在于這種情景下,如果發(fā)生“內(nèi)存重啟”后,因為Fragment轉(zhuǎn)場動畫沒結(jié)束時再執(zhí)行其他方法,會導(dǎo)致Fragment狀態(tài)不會被FragmentManager正常保存下來。
2、進入新的Fragment并立刻關(guān)閉當(dāng)前Fragment 時的一些問題(1)如果你想從當(dāng)前Fragment進入一個新的Fragment,并且同時要關(guān)閉當(dāng)前Fragment。由于數(shù)據(jù)結(jié)構(gòu)是棧,所以正確做法是先pop,再add,但是轉(zhuǎn)場動畫會有覆蓋的不正常現(xiàn)象,你需要特殊處理,不然會閃屏!
(2)Fragment的根布局要設(shè)置android:clickable = true,原因是在pop后又立刻add新的Fragment時,在轉(zhuǎn)場動畫過程中,如果你的手速太快,在動畫結(jié)束前你多點擊了一下,上一個Fragment的可點擊區(qū)域可能會在下一個Fragment上依然可用。
Tip:如果你遇到Fragment的mNextAnim空指針的異常(通常是在你的Fragment被重啟的情況下),那么你首先需要檢查是否操作的Fragment是否為null;其次在你的Fragment轉(zhuǎn)場動畫還沒結(jié)束時,你是否就執(zhí)行了其他事務(wù)等方法;解決思路就是延遲一個動畫時間再執(zhí)行事務(wù),或者臨時將該Fragment設(shè)為無動畫
看了上面的介紹,你可能會覺得Fragment有點可怕。
但是我想說,如果你只是淺度使用,比如一個Activity容器包含列表Fragment+詳情Fragment這種簡單情景下,不涉及到popBackStack/Immediate(tag/id)這些的方法,還是比較輕松使用的,出現(xiàn)的問題,網(wǎng)上都可以找到解決方案。
但是如果你的Fragment邏輯比較復(fù)雜,有特殊需求,或者你的app架構(gòu)是僅有一個Activity + 多個Fragment,上面說的這些坑,你都應(yīng)該全部解決。
在下一篇中,介紹了一些非常實用的使用技巧,包括如何解決Fragment嵌套、各種環(huán)境、組件下Fragment的使用等技巧,推薦閱讀!
還有一些比較隱蔽的問題,不影響app的正常運行,僅僅是一些顯示的BUG,并沒有在上面介紹,在本系列的最后一篇,我給出了我的解決方案,一個我封裝的Fragmentation庫,解決了所有動畫問題,非常適合單Activity+多Fragment 或者 多模塊Activity+多Fragment的架構(gòu)。有興趣的可以看看 :)
Fragment隨筆? 著作權(quán)歸作者所有舉報文章如果覺得我的文章對您有用,請隨意打賞。您的支持將鼓勵我繼續(xù)創(chuàng)作!
贊賞支持





等8人喜歡 419 更多分享120條評論 只看作者按喜歡排序按時間正序按時間倒序
coco貓16樓 · 2016.04.20 15:28你好 ,關(guān)于棧內(nèi)順序不正確,F(xiàn)ragmentTransactionBugFixHack要怎么使用,這部分沒看明白
贊 回復(fù)YoKey: @coco貓 在pop多個Fragment后,F(xiàn)ragmentTransactionBugFixHack.reorderIndices(FragmentManager)即可,也可以在add/replace Fragment之前調(diào)用一次 :)
2016.04.22 12:15 回復(fù)__Berial___: @YoKey 如何拿到 FragmentManagerImpl 這個只有包權(quán)限的類?創(chuàng)建相同的包?話說給的那個stackoverflow 的鏈接里沒有這樣的回答額。。
2016.05.19 10:45 回復(fù)YoKey: 作為一個類放入你工程下新建的android.support.v4.app這個包里就可以了,可以參考我第三篇里的Github里的源碼 ![]()
T摩天倫17樓 · 2016.04.22 12:25樓主,請教個問題,就是我項目是ViewPager + Fragment +RadioGroup的,但是每個Fragment里面還嵌套有Fragment,這樣從Fragment打開子Fragment是空白的,這是什么情況,用的是hide(),add() 。
贊 回復(fù)YoKey: @T摩天倫 需求是Fragment嵌套嗎? 是的話 ,add子Fragment時,使用父Fragment的getChildFragmentManager來操作,而不是用getFragmentManager :)
2016.04.22 12:48 回復(fù)T摩天倫: @YoKey 這個知道,用了getChildFragmentManager的話,app直接閃退,報錯:No view found .......
2016.04.22 13:26 回復(fù)YoKey: @T摩天倫 從這個錯,我猜可能是你使用了Activity的R.id.container作為containerViewId父Fragment.getChildFragmentManager().beginTransaction.add(containerViewId,子Fragment)...你應(yīng)該使用父Fragment的FrameLayout容器,作為containerViewId ![]()
滋滋滋Boom19樓 · 2016.05.03 13:58樓主,想問下,為什么使用onAttach(Activity activity)代替getActivity()沒有問題,但是使用onAttach(Context context)應(yīng)用會空指針異常,java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
贊 回復(fù)YoKey: @滋滋滋Boom 從異常來看是你的Context是null,檢查下你的context。應(yīng)該和onAttach沒什么關(guān)系。onAttach(Context context)這個方法是新的support包里新加的,是為了更安全的保證有宿主Activity。其源碼:public void onAttach(Context context) {mCalled = true;final Activity hostActivity = mHost == null ? null : mHost.getActivity();if (hostActivity != null) {mCalled = false;onAttach(hostActivity);}}
2016.05.03 14:05 回復(fù) 添加新評論
devYOUK20樓 · 2016.05.11 09:58很好的文章!
贊 回復(fù)
依米621樓 · 2016.05.11 17:15樓主將這些坑講解的很透徹,學(xué)習(xí)了。
![]()
喜歡而非堅持22樓 · 2016.05.11 17:18可能是我看過的關(guān)于Fragment系列文章中最好的.
贊 回復(fù)
imknown23樓 · 2016.05.11 23:10太棒了, 自己也走了好多 Fragment 的坑. 樓主的 提到的 那一個 兼容包 23.2 的問題 真的是太棒了. 我去 谷歌官網(wǎng)看了一下, The system now calls onActivityResult() for a nested FragmentActivity., 謝謝 哈哈
贊 回復(fù)
纖沫24樓 · 2016.05.13 14:20在csdn 上,看到有推薦這篇文章,看了非常不錯。
贊 回復(fù)
安哉25樓 · 2016.05.16 01:43學(xué)習(xí)啦
贊 回復(fù)
阿爾法貓26樓 · 2016.05.17 10:46樓主,能提供一下代碼嗎,我菜鳥,復(fù)制上去出現(xiàn)了很多沒見過的錯
贊 回復(fù)YoKey: @阿爾法貓 我的這系列第三篇文章里有g(shù)ithub地址包含Demo,不過建議新手避免深入使用Fragment,正常使用即可,可能第二篇更適合你,這一篇大部分內(nèi)容都是深入使用時才會遇到的坑 :)
2016.05.17 10:55 回復(fù)阿爾法貓: @YoKey 恩恩,謝謝
2016.05.17 12:01 回復(fù) 添加新評論
Jafir27樓 · 2016.05.19 04:58半夜起來打蚊子,看看干貨……看到 內(nèi)存重啟恢復(fù)那里,為什么只有倆個 ?一個是targetfragment 一個是hidefragment。 像QQ那樣 都是3 4個~ 這里的倆個 中的hide具體指的什么?應(yīng)該是除了要顯示的targetfragment之外的fragment吧~希望樓主指明
贊 回復(fù)YoKey: @Jafir
打蚊子... 是的 那里為了閱讀方便簡寫了下 就寫了一個hideFragment
ClownQiang28樓 · 2016.05.19 17:35博主你好~關(guān)于“FragmentManager棧中管理fragment下標(biāo)位置的數(shù)組ArrayList<Integer> mAvailIndeices的BUG”,這里我沒太理解問題,還有你給出的這一段源碼,我看了一下不太清楚問題在哪里,能否寫的更詳細一點~~謝謝啦
贊 回復(fù)YoKey: @ClownQiang f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent);mActive.set(f.mIndex, f);這兩句代碼,pop多個Fragment有時會導(dǎo)致mAvailIndices里的下標(biāo)順序出問題,導(dǎo)致Fragment的index錯誤,附帶mActive這個管理Fragment的List下標(biāo)錯誤
2016.05.19 17:42 回復(fù) 添加新評論
yangyirunning29樓 · 2016.05.20 12:02用心之作,干貨十足!博主辛苦了!
贊 回復(fù)
阿爾法貓30樓 · 2016.05.20 13:57哥哥,F(xiàn)ragment全解析系列(一)這個的源碼有嗎?就是Fragment重疊異常問題,我放在底部了,結(jié)果只顯示第一個的fragment,點擊其他的不執(zhí)行
贊 回復(fù)YoKey: @阿爾法貓
文章中的代碼都是核心代碼,是我特意寫的,源碼倒是沒有的;你這個問題,點擊其他沒作用的話,檢查下是否確定執(zhí)行了fragmentManager.beginTransaction().show(目標(biāo)Fragment).hide(當(dāng)前Fragment).commit(); ![]()
阿爾法貓: if (savedInstanceState != null) { // “內(nèi)存重啟”時調(diào)用tost.showToast("內(nèi)存重啟");List<Fragment> fragmentList = getSupportFragmentManager().getFragments();for (Fragment fragment : fragmentList) {if (fragment instanceof TruckFragment) {tracke = (TruckFragment) fragment;} else if (fragment instanceof accessoriesFragment) {accessories = (AccessoriesFragment) fragment;} else if (fragment instanceof MineFragment){mine= (MineFragment) fragment;} else if (fragment instanceof MessageFragment){message= (MessageFragment) fragment;}// 解決重疊問題getSupportFragmentManager().beginTransaction().show(tracke).hide(accessories).hide(message).hide(mine).commit();}}else{// 正常時tracke = TruckFragment.newInstance();accessories = AccessoriesFragment.newInstance();message=MessageFragment.newInstance();mine=MineFragment.newInstance();// // 這里add時,tag可傳可不傳getSupportFragmentManager().beginTransaction().add(R.id.frame_content,tracke).hide(accessories).hide(message).hide(mine).commit();}
2016.05.20 15:47 回復(fù) 添加新評論
阿爾法貓31樓 · 2016.05.20 15:47radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {switch (checkedId) {case R.id.chache:getSupportFragmentManager().beginTransaction().add(R.id.frame_content,tracke).hide(accessories).hide(message).hide(mine).commit();break;case R.id.accessories:getSupportFragmentManager().beginTransaction().add(R.id.frame_content,accessories).hide(tracke).hide(message).hide(mine).commit();break;case R.id.message:getSupportFragmentManager().beginTransaction().add(R.id.frame_content,message).hide(tracke).hide(accessories).hide(mine).commit();break;case R.id.mine:getSupportFragmentManager().beginTransaction().add(R.id.frame_content,mine).hide(tracke).hide(message).hide(accessories).commit();break;}}});
贊 回復(fù)YoKey: @阿爾法貓 這里給你一種簡寫方法,第一次就把4個Fragment都add到FM中(如果Fragment資源占用比較大時,再考慮切換目標(biāo)Fragment時才add這樣的方式)else{ // 正常時tracke = TruckFragment.newInstance();accessories = AccessoriesFragment.newInstance();message=MessageFragment.newInstance();mine=MineFragment.newInstance();// // 這里add時,tag可傳可不傳getSupportFragmentManager().beginTransaction().add(R.id.frame_content,tracke).add(R.id.frame_content,accessories).add(R.id.frame_content,message).add(R.id.frame_content,mine).hide(accessories).hide(message).hide(mine).commit();}切換時:getSupportFragmentManager().beginTransaction().show(mine) // add換成show.hide(tracke).hide(message).hide(accessories).commit();
2016.05.20 16:02 回復(fù)阿爾法貓: 真是太感謝您了,謝謝
2016.05.20 16:50 回復(fù)阿爾法貓: 已打賞。。謝謝了
2016.05.20 16:52 回復(fù) 添加新評論 還有1條評論, 展開查看上一頁 1 2 34 下一頁被以下專題收入,發(fā)現(xiàn)更多相似內(nèi)容
week.io
Android...
Android...
Android...
玩轉(zhuǎn)iOS &...
安卓必須知道的
程序員
Android那些事
Android
Android角落
Android開發(fā)
android...
Android實戰(zhàn)
Android...
andnroid加載更多...原文鏈接: http://www.jianshu.com/p/d9143a92ad94新聞熱點
疑難解答