這個首先從一個bug說起,如圖:
我們都知道fragment切換有兩種方式:
1. replace方式
transaction.replace(R.id.content, IndexFragment);
2. add-hide-show方式
transaction.add(R.id.content, IndexFragment); transaction.hide(otherfragment); transaction.show(thisfragment);
而上面按鈕中出現bug的就是采用第二種方式。然后我們來分析下用add,hide,show為什么出現這種bug,我把每個操作都打印出了以下日志:
復現bug的操作是:
1.首先打開,默認選中的是第一個tab,如上面的一張圖片正常那樣。
2.切換到tab2,並把tab1 hide掉;
3.再切回到tab1,並不會觸發tab1對應fragment的任何生命周期;
4.然后home鍵進入后台,我在activity的onPause()中手動對IndexFragment賦空,模擬長時間后台,系統銷毀了該引用。
IndexFragment=null;
5.再次啟動,其實tab1 的fragment實例在內存中還在,只是他的引用被銷毀了。
6.再切到tab2,這里其實是先把tab1的hide,在show tab2,但是tab1 的fragment引用為空,所以無法hide,就出現了tab2疊在tab1上的花屏情況。
7.再切到tab1,tab1就會重復創建對象。
同樣的操作,我們使用replace的方式
使用replace方式,雖然這種方式會避免上述的bug,但也是重復創建了對象。因為replace方式,對應的FrameLayout只有一 層,而add方式,這個FrameLayout其實有2層。但是這種方式的缺點是:每次replace會把生命周期全部執行一遍,如果在這些生命周期函數 里拉取數據的話,就會不斷重復的加載刷新數據。
那么最合適的處理方式是這樣的:
1.在add的時候,加上一個tab參數
transaction.add(R.id.content, IndexFragment,”Tab1″);
2.然后當IndexFragment引用被回收置空的話,先通過
IndexFragment=FragmentManager.findFragmentByTag(“Tab1″);
找到對應的引用,然后繼續上面的hide,show;