1. 程式人生 > >java.lang.IllegalStateException: Fragment already added問題

java.lang.IllegalStateException: Fragment already added問題

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