Caused by: java.lang.IllegalStateException: Fragment already active

Caused by: java.lang.IllegalStateException: Fragment already active
at android.app.Fragment.setArguments(Fragment.java:696)

...

위와 같은 에러가 난다면 setArguments()의 주석을 먼저 확인해보자.

/**
 * Supply the construction arguments for this fragment.  This can only
 * be called before the fragment has been attached to its activity; that
 * is, you should call it immediately after constructing the fragment.  The
 * arguments supplied here will be retained across fragment destroy and
 * creation.
 */
public void setArguments(Bundle args) {
    if (mIndex >= 0) {
        throw new IllegalStateException("Fragment already active");
    }
    mArguments = args;
}

프래그먼트를 위한 생성자 아규먼트를 제공하며, 이 프래그먼트가 액티비티에 붙기(attach)전에만 호출된다고 한다. 그러므로, 프래그먼트를 만들자 마자 호출해야 제대로 동작한다는 뜻이다.

그럼, 저 에러를 나는 부분의 코드를 살펴보자. 보통 프래그먼트를 만든 후에 1회 이상 액티비티에 붙인 후일 것이다. 그러므로, setArgument()를 호출하면 이 프래그먼트는 이미 활성화(active)되어있다며 에러가 뜨게된다.

위 소스를 보면 mIndex라는 값이 0과 같거나 큰 경우에 에러를 던지고 있으며, 저 값은 Fragment.initState() 안에서 -1(최초 기본값)로 초기화 된다. 그리고, initState()는 프래그먼트가 remove 된 경우에만 프래그먼트 매니저에 의해 호출된다. 아래를 참고하자.

/**
 * Called by the fragment manager once this fragment has been removed,
 * so that we don't have any left-over state if the application decides
 * to re-use the instance.  This only clears state that the framework
 * internally manages, not things the application sets.
 */
void initState() {
    mIndex = -1;
    mWho = null;
    mAdded = false;
    mRemoving = false;
    mResumed = false;
    mFromLayout = false;
    mInLayout = false;
    mRestored = false;
    mBackStackNesting = 0;
    mFragmentManager = null;
    mActivity = null;
    mFragmentId = 0;
    mContainerId = 0;
    mTag = null;
    mHidden = false;
    mDetached = false;
    mRetaining = false;
    mLoaderManager = null;
    mLoadersStarted = false;
    mCheckedForLoaderManager = false;
}

그러므로, 프래그먼트 매니저를 통해 프래그먼트를 remove 해준 후, 다시 사용할 때 setArgument()를 제대로 호출할 수 있다. 예를 들면, remove() 호출방법은 아래와 같다.

getFragmentManager().beginTransaction().remove(activeFragment).commit();

 

 

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.