由於這個項目的首頁是類似微信的那種 tab 有四個界面 聯繫人,消息,動態,設置四個界面,因爲有頻繁的切換,所以就沒有使用replace 和 remve方法。而是通過hide,show方式,這樣雖然不會重複創建Fragment了,節省了view重繪的性能問題。
但是這樣就容易導致一個問題:就是程序長時間後臺導致fragment重疊。
問題描述:
app運行的時候,按下home鍵,然後清理內存。
或者,按下home之後,打開其他的一些佔內存的app,然後把本app的內存擠掉了。
解決方案: (這個問題google了很多帖子,發現寫的很亂,沒幾個好用的,後來我就一個個的試驗,從兩個帖子中找到有用的方法。綜合如下:)
1:給每個Fragment加一個Tag;
2.在onCreate(Bundle savedInstanceState)中判斷Bundle savedInstanceState是否不爲空;
3.不爲空則進行find Tag,重新給幾個frament賦值。
1.
switch (index) {
case 0:
// 當點擊了消息tab時,改變控件的圖片和文字顏色
messageImage.setImageResource(R.drawable.message_selected);
messageText.setTextColor(Color.WHITE);
if (messageFragment == null) {
// 如果MessageFragment爲空,則創建一個並添加到界面上
messageFragment = new MessageFragment();
transaction.add(R.id.content, messageFragment, FRAGMENT_TAG[index]);
} else {
// 如果MessageFragment不爲空,則直接將它顯示出來
transaction.show(messageFragment);
}
break;
2. 3.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
// 初始化佈局元素
initViews();
fragmentManager = getFragmentManager();
if (savedInstanceState != null) {
//讀取上一次界面Save的時候tab選中的狀態
selindex=savedInstanceState.getInt(PRV_SELINDEX,selindex);
messageFragment = (MessageFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[0]);
contactsFragment = (ContactsFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[1]);
newsFragment = (NewsFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[2]);
settingFragment = (SettingFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[3]);
}
// 選中index
setTabSelection(selindex);
}
//那麼文中有幾處藍色高亮的代碼 請看如下
/**
* Fragment的TAG 用於解決app內存被回收之後導致的fragment重疊問題
*/
private static final String[] FRAGMENT_TAG = {"msgfrag","contacfrag","actfrag","settfrag"};
PS:
補充一點:PRV_SELINDEX,selindex 是用於恢復上一次界面Save的時候tab選中的狀態
@Override
protected void onSaveInstanceState(Bundle outState) {
//保存tab選中的狀態
outState.putInt(PRV_SELINDEX,selindex);
super.onSaveInstanceState(outState);
}
/**
* 上一次界面 onSaveInstanceState 之前的tab被選中的狀態 key 和 value
*/
private static final String PRV_SELINDEX="PREV_SELINDEX";
private int selindex=0;
OK,當你配置好了tag之後,再addfrag的時候使用了tag,Act執行saveInstancestates 的時候就會自動按tag給你保存frag的狀態了。
那麼,你如果覺得這種方式不是很好,你這tag也可以不要在add的時候使用,你可以在Act onSAveInstancestate的時候,用FragmentMange手動保存,
然後在act,oncreate的時候bundle不爲空 就用之前記錄的幾個tag手動打開。
這是這個act裏面的Frag的問題。
2.那麼frag中嵌套frag的時候,也是需要保存與恢復的呢?
frag中的frag是子frag,外層的frag是主frag。先這麼叫吧,這樣好區分。
一樣的道理 ,代碼都很像,你把主frag當成act,只是getSurpportFragmentManager的時候 ,不用這個方法,有個getChildFragmentManger,大概是這麼寫的吧,我記不清是getChildFfragmentMnager還是getSurpportChildFragmentmanager了,反正你找下就行了。
這裏就不貼代碼了,畢竟很act中潛逃frag代碼都很像,邏輯都是一樣的。
3.有點要注意的是viewpager中潛逃frag,這樣的話 記得把Viewpager的緩存數設置爲 frag 數目減一。viewpager有個方法是setoffscreenpagelimit方法,可以設置緩存數目,這個方法看viewpager的源碼,意思是緩存下來未顯示的子控件,所以viewpager肯定是有一個是顯示的,其他的要緩存,那麼緩存數是 子控件的數目減一。 而且從viewpager的源碼上看,這個方法裏,最小的數字是1。
緩存數 默認也是1,你不改的話 他會 有一些問題,就是你這邊的frag因爲沒有被緩存 會被自動釋放,然後重新新建,有些邏輯執行的就比較多了 。
viewpager內嵌套frag之後,每次pagerAdapger 執行notifychange的時候會有個問題就是特麼的,原來的舊的fragment會先釋放,執行ondettach ondestory方法 ,然後重新創建,要注意。
無恥的奉上我的公衆號二維碼,沒事聽我給你扯扯段子。