在通过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。