java.lang.IllegalStateException: Fragment already added問題
阿新 • • 發佈:2019-02-06
在通過fragmentmanager管理fragment棧的時候,出現了java.lang.IllegalStateException: Fragment already added的錯誤,導致Email 應用程式出現FC。網上建議通過檢查isAdded()函式來檢查它是否已經被新增進棧中。
但在實際使用時,卻發現這個檢查並不準確。我在下面的show方法前呼叫了isAdded()方法,發現在出現此FC問題前,此方法的返回值一直是false。
public void showDownloadingDialog() {
final FragmentTransaction ft = mFragmentManager.beginTransaction();
final Fragment prev = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
// Create and show the dialog.
final DialogFragment newFragment = AttachmentProgressDialogFragment.newInstance(
mAttachment);
newFragment.show(ft, PROGRESS_FRAGMENT_TAG);
}
在fragment.java中檢視此show()方法:
public int show(FragmentTransaction transaction, String tag) { mDismissed = false; mShownByMe = true; transaction.add(this, tag); mViewDestroyed = false; mBackStackId = transaction.commit(); return mBackStackId; }
實際上,isAdded()方法這個值是在FragmentManager.java中修改的。
final public boolean isAdded() {
return mActivity != null && mAdded;
}
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (mAdded == null) {
mAdded = new ArrayList<Fragment>();
}
if (DEBUG) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
moveToState(fragment);
}
}
}
而在Email 的程式碼中,由於快速多次點選,會多次呼叫showDownloadingDialog()方法。導致fragment.java中show()方法也被多次呼叫。然而上面的addFragment()方法沒有被及時呼叫,出現mAdded的值一直為false。
因此,正確的方法去避免重複新增fragment,應該重寫show和dismiss函式
並用一個boolean變數去記錄新增情況,通過檢查這個值來避免重複新增fragment的情況。
@Override
public int show(FragmentTransaction transaction, String tag) {
// TODO Auto-generated method stub
Log.i(TAG," AttachmentProgressDialogFragment22 show:"+isFragmentShown);
if(!isFragmentShown){
isFragmentShown = true;
return super.show(transaction, tag);
}
return -1;
}
在dismiss中將這個值修改為false。