Fragment_배우다

6159 단어

fragment 운영 프로세스


Fragment 초기화의 구체적인 절차를 살펴보겠습니다.add () 를 예로 들면 다음과 같습니다.
FragmentManager:
 @Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

FragmentTranscation 유형의 BackStackRecord 객체를 먼저 가져옵니다.
BackStackRecord:
FragmentTranscaction에서 add()를 호출하면 사용자의 작업을 저장하는 새 Op 클래스가 생성됩니다.
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        fragment.mFragmentManager = mManager;
        ...
        Op op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
    }
void addOp(Op op) {
        if (mHead == null) {
            mHead = mTail = op;
        } else {
            op.prev = mTail;
            mTail.next = op;
            mTail = op;
        }
        op.enterAnim = mEnterAnim;
        op.exitAnim = mExitAnim;
        op.popEnterAnim = mPopEnterAnim;
        op.popExitAnim = mPopExitAnim;
        mNumOp++;
    }

이후 BackStackRecord의 두 개의 Op 클래스(mHead, mTail)로 사용자의 동작을 체인 테이블 형식으로 저장합니다.
mHead, 가입할 때 두루 돌아다닌다.
mTail, 백이 종료될 때 옮겨다니기.
마지막으로 커밋()이 어떻게 이루어졌는지 봅시다.
우선saveStack으로 설정하면 현재 BackStackRecord 대상add를 Fragment Manager의 mBackStackIndices(Arraylist)에 되돌려주고list를 되돌려줍니다.크기 () 를 Id로 사용합니다.
 int commitInternal(boolean allowStateLoss) {
        ...
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

Fragment Manager는 이 BackStack 객체를 의Handle 대기열에 추가하여 실행합니다.처리 중인 Runnable이 mPendingActions에 저장됩니다.excutePendingTransactions () 를 사용하여 mPendingActions의run을 즉시 반복할 수 있습니다.
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mActivity.mHandler.removeCallbacks(mExecCommit);
mActivity.mHandler.post(mExecCommit);
}

run에서 사용자 작업 상태(cmd)에 따라 mHead 체인 테이블을 옮겨다니며 Fragment Manager에 대응하는 방법을 실행합니다. 여기서 비교적 특수한 것은 Replace()입니다.마지막으로 관리자의 mBackStack 컬렉션에 BackStack 객체 저장
 public void run() {
        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);

        if (mAddToBackStack) {
            if (mIndex < 0) {
                throw new IllegalStateException("addToBackStack() called after commit()");
            }
        }

        bumpBackStackNesting(1);

        Op op = mHead;
        while (op != null) {
            switch (op.cmd) {
                case OP_ADD: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    mManager.addFragment(f, false);
                } break;
                case OP_REPLACE: {
                    Fragment f = op.fragment;
                    if (mManager.mAdded != null) {
                        for (int i=0; i<mManager.mAdded.size(); i++) {
                            Fragment old = mManager.mAdded.get(i);
                            if (FragmentManagerImpl.DEBUG) Log.v(TAG,
                                    "OP_REPLACE: adding=" + f + " old=" + old);
                            if (f == null || old.mContainerId == f.mContainerId) {
                                if (old == f) {
                                    op.fragment = f = null;
                                } else {
                                    if (op.removed == null) {
                                        op.removed = new ArrayList<Fragment>();
                                    }
                                    op.removed.add(old);
                                    old.mNextAnim = op.exitAnim;
                                    if (mAddToBackStack) {
                                        old.mBackStackNesting += 1;
                                        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
                                                + old + " to " + old.mBackStackNesting);
                                    }
                                    mManager.removeFragment(old, mTransition, mTransitionStyle);
                                }
                            }
                        }
                    }
                    if (f != null) {
                        f.mNextAnim = op.enterAnim;
                        mManager.addFragment(f, false);
                    }
                } break;
               ...
                default: {
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
                }
            }

            op = op.next;
        }

        mManager.moveToState(mManager.mCurState, mTransition,
                mTransitionStyle, true);

        if (mAddToBackStack) {
            mManager.addBackStackState(this);
        }
    }

여기의 mAddeded는 add가 들어오는fragment 대상을 저장하는 데 사용되는 Manager의 List입니다.여기에 간단한 비교를 했는데 만약에 새로운fragment와List의fragment가 같은 대상이라면 직접 건너뛰고 아무것도 하지 않는다.
만약 같은 대상이 아니라면, 리스트의fragment를 삭제합니다.이렇게 쓰면 마지막 GruopView에는 최신 교체된 Fragment만 남게 됩니다.
그러나 실험을 통해 여러 개의fragment를 같은 Gruop VIew에 넣고 Replace () 를 하면 마지막 프레임만 바뀌고 첫 번째는 사라지고 그가 보류하는 상황이 나타난다는 것을 발견했다.여기서 나는 또 다시 보아야 한다. 만약 아는 친구가 있다면 나에게 어떻게 된 일인지 알려줄 수 있다.
FragmentManager:
새 Fragment를 총 집합(Array List < Fragment > mAdded)과 활성 집합(Array List < Fragment > mActive)에 추가한 후 구체적인 작업은 모두 move ToState에서 실행됩니다.
public void addFragment(Fragment fragment, boolean moveToStateNow) {
        if (mAdded == null) {
            mAdded = new ArrayList<Fragment>();
        }
       ...
        makeActive(fragment);
        if (!fragment.mDetached) {
            ...
            mAdded.add(fragment);
            if (moveToStateNow) {
                moveToState(fragment);
            }
        }
    }
   

moveToState 학습, 보기3

좋은 웹페이지 즐겨찾기