ページ

2015年7月13日月曜日

FragmentがActivityからAtachされているか判定

タイミングによって、Fragment内でgetString(R.string.〜)を使った際に
ActivityからAtachされてないとこける。

java.lang.IllegalStateException: Fragment XXXXX not attached to Activity

これはgetString内のgetResourcesでActivityからのAtachチェックを行っている為。
↓ android.app.Framgnet.java 抜粋
 final public Resources getResources() {
     if (mActivity == null) {
         throw new IllegalStateException("Fragment " + this + " not attached to Activity");
     }
     return mActivity.getResources();
 }

回避策としてFrament#isAddedでチェックする
↓ android.app.Framgnet.java 抜粋
final public boolean isAdded() {
     return mActivity != null && mAdded;
 }

例) ActivityからAtachされる前にスレッド実行する際にisAddedメソッドでチェック
@Override
protected void onPostExecute(Void result){
    if(isAdded()){
        getResources().getString(R.string.app_name);
    }
}

mAddedに関して
mAdded(boolean)はFragmentManagerの以下メソッドで設定している
・mAdded = true
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);
        }
   }
}

・mAdded = false
public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
    if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
    final boolean inactive = !fragment.isInBackStack();
    if (!fragment.mDetached || inactive) {
        〜中略〜
        if (mAdded != null) {
            mAdded.remove(fragment);
        }
        if (fragment.mHasMenu && fragment.mMenuVisible) {
            mNeedMenuInvalidate = true;
        }

    if (!fragment.mDetached) {
        if (mAdded.contains(fragment)) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }
        fragment.mAdded = false;
        fragment.mRemoving = true;
        moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                    transition, transitionStyle, false);
   }
}

※上記に関してはandroid.support.v4.app.Fragmentでも同じ


1 件のコメント: