問題
當快速點擊切換不一樣的Fragment的時候部分手機的app居然掛了,報出了下面的錯誤 Fragment already added
java.lang.IllegalStateException: Fragment already added: xxxxFragmentjava
上網找了不少,大體獲得的緣由是當快速雙擊調用FragmentTransaction.add()方法添加fragmentA,而fragmentA不是每次單獨生成的,就會引發這個異常。
上面的內容是網上的解釋,不過我認爲是由於同一個Fragment被add兩次致使的錯誤,可是奇怪的是我在加載這個Fragment的時候已經作了是否add的判斷,爲何還會有這個問題呢。
private void addFragment(FragmentManager fm, Fragment fragment ) {
Log.i( "addFragment", "### " + fragment.getId() + " " + fragment.isAdded() + " " + fragment.isHidden() ); if (!fragment.isAdded() ) { FragmentTransaction ft = fm.beginTransaction(); fm.executePendingTransactions(); ft.add( R.id.main_content, fragment ); ft.commitAllowingStateLoss(); }
經過打印結果發現,第一次切換到FragmentA的時候,FragmentA明明已經add了,可是isAdded()依然顯示false
addFragment: ###1 2131755357 false true addFragment: ###2 2131755357 false true addFragment: ###3 2131755357 false true addFragment: ###4 2131755357 false true
第二次切換到相同FragmentA的時候isAdded()就顯示爲true了
addFragment: ###1 2131755357 true true addFragment: ###2 2131755357 true true addFragment: ###3 2131755357 true true addFragment: ###4 2131755357 true true
在不斷快速切換不一樣的Fragment的時候,isAdded()偶爾會顯示false,就由於isAdded()顯示了false,那麼 ft.add( R.id.main_content, fragment )就會再次執行一次,就會報錯,說明經過isAdded()這個方法判斷Fragment是否被add可能並不許確。
方法
解決方法就是每次add的時候加上一個tag,而後不只要經過isAdded()判斷Fragment是否add,還要經過FragmentManager.findFragmentByTag(tag)獲取Fragment,而後判斷此Fragment是否爲null。
case R.id.home_tab_a: hideAllFragment( fm ); addFragment( fm, fragmentA, "A" ); showFragment( fm, fragmentA ); break; case R.id.home_tab_b: hideAllFragment( fm ); addFragment( fm, fragmentB, "B" ); showFragment( fm, fragmentB ); break; case R.id.home_tab_c: hideAllFragment( fm ); addFragment( fm, fragmentC, "C" ); showFragment( fm, fragmentC ); break;
影藏全部的Fragment
private void hideAllFragment(FragmentManager fm) { FragmentTransaction ft = fm.beginTransaction(); if (!shijianFragment.isHidden()) ft.hide( fragmentA ); if (!riliFragment.isHidden()) ft.hide( fragmentB ); if (!gongjuFragment.isHidden()) { ft.hide( fragmentC ); } ft.commitAllowingStateLoss(); }
經過isAdded()判斷Fragment是否add,同時經過tag獲取Fragment,判斷Fragment是否爲空,雙重判斷
private void addFragment(FragmentManager fm, Fragment fragment, String tag) { if (!fragment.isAdded()&&null == fm.findFragmentByTag( tag )) { FragmentTransaction ft = fm.beginTransaction(); fm.executePendingTransactions(); ft.add( R.id.main_content, fragment, tag ); ft.commitAllowingStateLoss(); } }
顯示Fragment
private void showFragment(FragmentManager fm, Fragment fragment) { FragmentTransaction ft = fm.beginTransaction(); ft.show( fragment ); ft.commitAllowingStateLoss(); }