1. 程式人生 > >Fragment經典問題——記憶體銷燬導致fragment重疊

Fragment經典問題——記憶體銷燬導致fragment重疊

今天QA提了一個bug,說我們的程式首頁怎麼突然像一堆翔一樣……我剛要發作,看了看她的螢幕,真TM像一堆翔,所有頁面都重疊在了一起!WTF!

講真,做Android這麼久還是第一次遇到fragment重疊的問題,之前只看過一些資料,這次終於趕上活的了!

來分析下原因。我們首頁是一個FragmentActivity,裡面有四個Fragment,通過show和hide維護各個頁面。當記憶體不足時,我們的宿主FragmentActivity被銷燬,而所有的Fragment例項被快取下來,則再回來首頁時,快取的fragment又重新被加載出來,此時show和hide對這些快取下來的Fragment例項無效,於是便出現重疊。

所以這種場景需要我們自己維護savedInstanceState快取檢視,在onCreate的時候根據savedInstanceState是否為空來判斷,是走正常的onCreate流程,還是給快取的檢視繫結資料的流程。

程式碼例項

@Override
protected void onCreate(Bundle savedInstanceState) {
    ……
    if (savedInstanceState != null) {
        //不為空說明快取檢視中有fragment例項,通過tag取出來
        FragmentManager fragmentManager= getFragmentManager();
        fragment1 = (MyFragment1) fragmentManager.findFragmentByTag("MyFragment1"
); fragment2 = (MyFragment2) fragmentManager.findFragmentByTag("MyFragment2"); }else{ fragment1 = findOrCreateFragment("MyFragment1", MyFragment1.class); fragment2 = findOrCreateFragment("MyFragment2", MyFragment2.class); } ……//資料繫結 } @Nullable private <T extends Fragment> T findOrCreateFragment
(String tag, Class<T> fragmentClass) { Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag); if (fragment == null) { try { fragment = fragmentClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); return null; } } return (T) fragment; } /** * 通過該方法切換Fragments **/ private void switchToFragment(int position) { mSelectPosition = position; Fragment showFragment = mFragmentList.get(position); if (showFragment != mLastFragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); if (mLastFragment != null) { transaction.hide(mLastFragment); } if (!showFragment.isAdded()) { transaction.add(R.id.main_container, showFragment, showFragment.getClass().getName()).commitAllowingStateLoss();// 隱藏當前的fragment,顯示選中的fragment } else { transaction.show(showFragment).commitAllowingStateLoss();// 隱藏當前的fragment,顯示選中的fragment } mLastFragment = showFragment; }

測試技巧

如果想重現上述場景,可開啟開發者選項中的“不保留後臺活動”,保證每次切換頁面,都殺死上個頁面。