1. 程式人生 > >Android fragment 重疊問題的解決方法

Android fragment 重疊問題的解決方法

由於這個專案的首頁是類似微信的那種 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方法  ,然後重新建立,要注意。 無恥的奉上我的公眾號二維碼,沒事聽我給你扯扯段子。