最近都在處理當 app 在後台時,ram 被清除所產生的一些問題,主要就是推播點進來怪怪的,資料回復不完全,還有就是 fragment 的行為不符合預期,以前都沒深究這些,正常 run ok 就 ok ,可是現在多了很多裝置維護的工具,幫你釋放記憶體,所以一些隱藏的問題就慢慢浮現,顯然本公司的前員工也不是很 care 這件事XD,感謝他們讓我有事做,順便讓我好好釐清 fragment 的行為。
主要就是 fragment 的 add 、replace、remove
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment f3 = new TestFragment3();
fragmentTransaction.replace(R.id.containerF, f3, "AAA");//tag fragment
or
fragmentTransaction.add(R.id.containerF, f3, "AAA");//tag fragment
fragmentTransaction.addToBackStack(null); //加入BackStack=需要按一次back
fragmentTransaction.commit();
add 就是在容器上添加 fragment
replace 就是替換這個容器的所有 fragment
查看目前一共有多少 fragment
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
查看目前有多少 fragment 被加到 BackStack
getSupportFragmentManager().getBackStackEntryCount()
依序進行 add、replace 與 remove
add f >> fragmentList .size = 1 BackStackEntryCount = 1
add f >> fragmentList .size = 2 BackStackEntryCount = 2
replace f >> fragmentList .size = 1 BackStackEntryCount = 3
remove f >> fragmentList .size = 0 BackStackEntryCount = 3
此時畫面因為remove fragment 而剛好 fragmentList .size =0 所以畫面為空,但是還是要按3 次back 才會回到底部,remove 不會減少 BackStackEntryCount,只會讓 fragment 從視圖移除。
按1次back >> fragmentList .size = 2 BackStackEntryCount = 2
按了1次back後,畫面就變回 f 的畫面,剛剛add 的兩個 f 又回到 list 裡,真的很有意思。
按1次back >> fragmentList .size = 1 BackStackEntryCount = 1
按1次back >> fragmentList .size = 0 BackStackEntryCount = 0
回到底部。
也因為這樣,若我只想要移除某一種 tag 的 fragment 辦不到,也無法針對某個 tag 的 fragment popBackStack,變成只能先讓所有的 fragment 出棧再 add 或 replace 想要的 fragment。
退出所有 BackStack 的 fragment fragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
目前公司的 fragment add 跟 replace 交錯使用,造成混亂,比方說我一次性的出棧所有 fragment,但是有些 add 後又 replace 的 fragment 因為 replace 的 fragment 先被出棧,底下 add 的 fragment 來不及重建就迅速被出棧,導致在 onDestroy 如果有調用物件要做 null check,不然就會掛掉, 也許在當初設計時根本沒想到這些,也沒有想到如果在畫面上已經有 fragment,推播進來 fragment 的流程是如何,導致現在要改也是牽一髮動全身,可怕!
沒有留言:
張貼留言