天天看點

大話Fragment管理

  上一個項目遇到了一個Activity 管理30個Fragment的情況,剛開始的時候真的管理的焦頭爛額,但是後來不停的研究api文檔,漸漸的明白了android的Fragment管理體系。下面用一種Fragment嵌套Fragment的情況來總結一下Fragment的管理。

大話Fragment管理

  大神立馬就能看出來,最外面一個Activity,底下首頁,分類,購物車..是第一層一個FragmentTabHost,而首頁裡面的類别01,02....是用的開源庫TabPageIndicator管理的ViewPager,管理這第二層的n個Fragment。

  1.當遇到這種嵌套多層的Fragment的時候第一個主要點就是第一層的FragmentManager,可以通過getSupportFragmentManager()或者getFragmentManager()獲得,但是在第二層的fragment中如果想獲得FragmentManager就不能這樣了,必須用getChildFragmentManager()。

  2.當點選一個其中一個商品的詳情的時候,如果想保持底部的TabHost那就不能用Activity,還得保持Fragment,其實還有另一中方案,那就是最外面的Activity用TabHostActivity,為什麼沒用尼,因為TabHostActivity已經被廢棄了,當我看到那條廢棄的橫線時,就好像看到一個美女臉上被刀開花了一樣,心痛啊,不能娶這樣的媳婦啊,直接換FragmentTabHost,黃花大閨女,唉呀媽呀,老裝逼了。回到需求,當點選其中一個商品時候,要将底部的TabHost保持,上面的布局都換成詳情的布局,看下Api,FragmentTransaction提供add,replace倆個方法,那麼用add還是replace尼?使用add()加入fragment時将觸發onAttach(),使用attach()不會觸發onAttach(),使用replace()替換後會将之前的fragment的view從viewtree中删除。

  觸發順序:

  detach()->onPause()->onStop()->onDestroyView()

  attach()->onCreateView()->onActivityCreated()->onStart()->onResume()

  使用hide()方法隻是隐藏了fragment的view并沒有将view從viewtree中删除,随後可用show()方法将view設定為顯示

  而使用detach()會将view從viewtree中删除,和remove()不同,此時fragment的狀态依然保持着,在使用attach()時會再次調用onCreateView()來重繪視圖,注意使用detach()後fragment.isAdded()方法将傳回false,在使用attach()還原fragment後isAdded()會依然傳回false(需要再次确認)

  執行detach()和replace()後要還原視圖的話, 可以在相應的fragment中保持相應的view,并在onCreateView()方法中通過view的parent的removeView()方法将view和parent的關聯删除後傳回。

  3.在複雜的Fragment管理中,經常會遇到 Fragment already added 錯誤,解決這樣的錯誤方法就是,每次添加Fragment,先findFragmentByTag,如果找到了fragment.isAdded(),那麼就return,跳出,如果Fragment沒在棧中,那就把Fragment Add上去,下面放出一個Fragment管理的公用類

  java代碼

/**
 * Fragment跳轉
 * @param fm
 * @param fragmentClass
 * @param tag
 * @param args
 */
public void turnToFragment(FragmentManager fm, Class<? extends Fragment> fragmentClass, String tag, Bundle args) {
    mIsCanEixt = false;
    Fragment fragment = fm.findFragmentByTag(tag);
    boolean isFragmentExist = true;
    if (fragment == null) {
        try {
            isFragmentExist = false;
            fragment = fragmentClass.newInstance();
            fragment.setArguments(new Bundle());
        } catch (java.lang.InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    if(fragment.isAdded()){
        return;
    }
    if( args != null && !args.isEmpty() ) {
        fragment.getArguments().putAll(args);
    }
    FragmentTransaction ft = fm.beginTransaction();
    ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out,
            android.R.anim.fade_in, android.R.anim.fade_out);
    if( isFragmentExist ) {
        ft.replace(R.id.realtabcontent, fragment);
    } else {
        ft.replace(R.id.realtabcontent, fragment, tag);
    }
                               
    ft.addToBackStack(tag);
    ft.commitAllowingStateLoss();
}      

最後為什麼用

ft.commitAllowingStateLoss();

繼續閱讀