• ViewPager部分源码分析二:FragmentManager对Fragment状态的管理完成ViewPager的child添加或移出


    ViewPager维护child代码流程:

    注:PagerAdapter 使用的是FragmentPagerAdapter类或者它的子类。

    viewPager.populate():

    void populate(int newCurrentItem) {
            ItemInfo oldCurInfo = null;
            if (mCurItem != newCurrentItem) {
                oldCurInfo = infoForPosition(mCurItem);
                mCurItem = newCurrentItem;
            }
    
            if (mAdapter == null) {
                sortChildDrawingOrder();
                return;
            }
    
            // Bail now if we are waiting to populate.  This is to hold off
            // on creating views from the time the user releases their finger to
            // fling to a new position until we have finished the scroll to
            // that position, avoiding glitches from happening at that point.
            if (mPopulatePending) {
                if (DEBUG) Log.i(TAG, "populate is pending, skipping for now...");
                sortChildDrawingOrder();
                return;
            }
    
            // Also, don't populate until we are attached to a window.  This is to
            // avoid trying to populate before we have restored our view hierarchy
            // state and conflicting with what is restored.
            if (getWindowToken() == null) {
                return;
            }
    
            mAdapter.startUpdate(this);
    
            final int pageLimit = mOffscreenPageLimit;
            final int startPos = Math.max(0, mCurItem - pageLimit);
            final int N = mAdapter.getCount();
            final int endPos = Math.min(N-1, mCurItem + pageLimit);
    
            if (N != mExpectedAdapterCount) {
                String resName;
                try {
                    resName = getResources().getResourceName(getId());
                } catch (Resources.NotFoundException e) {
                    resName = Integer.toHexString(getId());
                }
                throw new IllegalStateException("The application's PagerAdapter changed the adapter's" +
                        " contents without calling PagerAdapter#notifyDataSetChanged!" +
                        " Expected adapter item count: " + mExpectedAdapterCount + ", found: " + N +
                        " Pager id: " + resName +
                        " Pager class: " + getClass() +
                        " Problematic adapter: " + mAdapter.getClass());
            }
    
            // Locate the currently focused item or add it if needed.
            int curIndex = -1;
            ItemInfo curItem = null;
            for (curIndex = 0; curIndex < mItems.size(); curIndex++) {
                final ItemInfo ii = mItems.get(curIndex);
                if (ii.position >= mCurItem) {
                    if (ii.position == mCurItem) curItem = ii;
                    break;
                }
            }
    
            if (curItem == null && N > 0) {
           // 第一次初始化数据的时候会进入此处执行 curItem
    = addNewItem(mCurItem, curIndex); } // Fill 3x the available width or up to the number of offscreen // pages requested to either side, whichever is larger. // If we have no current item we have no work to do. if (curItem != null) { float extraWidthLeft = 0.f; int itemIndex = curIndex - 1; ItemInfo ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; final int clientWidth = getClientWidth();
           // 这里不知道为什么要加上Padding部分??这样,就可能导致ViewPager里存活的Item比没有Padding时要多。  
    final float leftWidthNeeded = clientWidth <= 0 ? 0 : 2.f - curItem.widthFactor + (float) getPaddingLeft() / (float) clientWidth; for (int pos = mCurItem - 1; pos >= 0; pos--) {
                    // 如果有Padding部分的存在,leftWidthNeeded比extraWidthLeft大一点,这样Item就没有被删除。
    if (extraWidthLeft >= leftWidthNeeded && pos < startPos) { if (ii == null) { break; } if (pos == ii.position && !ii.scrolling) { mItems.remove(itemIndex); mAdapter.destroyItem(this, pos, ii.object); if (DEBUG) { Log.i(TAG, "populate() - destroyItem() with pos: " + pos + " view: " + ((View) ii.object)); } itemIndex--; curIndex--; ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; } } else if (ii != null && pos == ii.position) { extraWidthLeft += ii.widthFactor; itemIndex--; ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; } else { ii = addNewItem(pos, itemIndex + 1); extraWidthLeft += ii.widthFactor; curIndex++; ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; } } float extraWidthRight = curItem.widthFactor; itemIndex = curIndex + 1; if (extraWidthRight < 2.f) { ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; final float rightWidthNeeded = clientWidth <= 0 ? 0 : (float) getPaddingRight() / (float) clientWidth + 2.f; for (int pos = mCurItem + 1; pos < N; pos++) { if (extraWidthRight >= rightWidthNeeded && pos > endPos) { if (ii == null) { break; } if (pos == ii.position && !ii.scrolling) { mItems.remove(itemIndex); mAdapter.destroyItem(this, pos, ii.object); if (DEBUG) { Log.i(TAG, "populate() - destroyItem() with pos: " + pos + " view: " + ((View) ii.object)); } ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; } } else if (ii != null && pos == ii.position) { extraWidthRight += ii.widthFactor; itemIndex++; ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; } else { ii = addNewItem(pos, itemIndex); itemIndex++; extraWidthRight += ii.widthFactor; ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; } } } calculatePageOffsets(curItem, curIndex, oldCurInfo); } if (DEBUG) { Log.i(TAG, "Current page list:"); for (int i=0; i<mItems.size(); i++) { Log.i(TAG, "#" + i + ": page " + mItems.get(i).position); } } mAdapter.setPrimaryItem(this, mCurItem, curItem != null ? curItem.object : null);      // 此处是ViewPager增加或删除child的入口。 mAdapter.finishUpdate(this); // Check width measurement of current pages and drawing sort order. // Update LayoutParams as needed. final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); lp.childIndex = i; if (!lp.isDecor && lp.widthFactor == 0.f) { // 0 means requery the adapter for this, it doesn't have a valid width. final ItemInfo ii = infoForChild(child); if (ii != null) { lp.widthFactor = ii.widthFactor; lp.position = ii.position; } } } sortChildDrawingOrder(); if (hasFocus()) { View currentFocused = findFocus(); ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null; if (ii == null || ii.position != mCurItem) { for (int i=0; i<getChildCount(); i++) { View child = getChildAt(i); ii = infoForChild(child); if (ii != null && ii.position == mCurItem) { if (child.requestFocus(View.FOCUS_FORWARD)) { break; } } } } } }

    viewPager.addNewItem():

    ItemInfo addNewItem(int position, int index) {
            ItemInfo ii = new ItemInfo();
            ii.position = position;
         // instantiateItem()之后的一系列方法调用,最终将增加项目这个操作添加到一个双向链表中。 ii.object
    = mAdapter.instantiateItem(this, position);
         // getPageWidth()默认返回1.f,可以通过overrid此方法控制一屏显示多个item。 ii.widthFactor
    = mAdapter.getPageWidth(position); if (index < 0 || index >= mItems.size()) { mItems.add(ii); } else { mItems.add(index, ii); } return ii; }

    fragmentPagerAdapter.instantiateItem():


    在实例化FragmentPagerAdapter对象时,传入的是FragmentActivit.getSupportFragmentManager(),通过查阅原代码,发现最终传入的FragmentManagerImpl实例。
    FragmentManagerImpl是FragmentManager一个内部类并且继承了FragmentManager

    
    
    public FragmentPagerAdapter(FragmentManager fm) {
            mFragmentManager = fm;
        }

    public
    Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) {
    // 因此此处实际是调用FragmentManagerImpl的beginTransaction()方法;
         // 而返回的是BackStackRecord的实例。
    mCurTransaction
    = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
    // 所以此处调用的是BackStackRecord的add()方法。 mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); }
    if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }

    fragmentManagerImpl.beginTransaction():

    public FragmentTransaction beginTransaction() {
            return new BackStackRecord(this);
        }

    backStackRecord.add():

    public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
            doAddOp(containerViewId, fragment, tag, OP_ADD);
            return this;
        }

    backStackRecord.doAddOp():

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
            fragment.mFragmentManager = mManager;
    
            if (tag != null) {
                if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
                    throw new IllegalStateException("Can't change tag of fragment "
                            + fragment + ": was " + fragment.mTag
                            + " now " + tag);
                }
                fragment.mTag = tag;
            }
    
            if (containerViewId != 0) {
                if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
                    throw new IllegalStateException("Can't change container ID of fragment "
                            + fragment + ": was " + fragment.mFragmentId
                            + " now " + containerViewId);
                }
                fragment.mContainerId = fragment.mFragmentId = containerViewId;
            }
    
            Op op = new Op();
            op.cmd = opcmd;
            op.fragment = fragment;
            addOp(op);
        }

    backStackRecord.addOp():

    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++;
        }

    以上流程就完成了添加child的准备工作。

    删除child的流程:

    在populate()方法的for循环中,当child过多时就会进行删除(通过宽度进行控制),删除代码:mAdapter.destroyItem,实际调用的是fragmentPagerAdapter.destroyItem.

    fragmentPagerAdapter.destroyItem():

    public void destroyItem(ViewGroup container, int position, Object object) {
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
            if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
                    + " v=" + ((Fragment)object).getView());
     // 实际调用的是BackStackRecord的detach()方法。
         // 因为mCurTransaction实际是一个BackStackRecord实例对象,具体参见:fragmentPagerAdapter.instantiateItem(): mCurTransaction.detach((Fragment)object); }

    backStackRecord.detach():

    public FragmentTransaction detach(Fragment fragment) {
            Op op = new Op();
            op.cmd = OP_DETACH;
            op.fragment = fragment;
            addOp(op);
    
            return this;
        }

    至此完成了删除child的准备工作。

    最终的添加或删除工作还得回到populate()方法:mAdapter.finishUpdate

    fragmentPagerAdapter.finishUpdate():

    public void finishUpdate(ViewGroup container) {
            if (mCurTransaction != null) {
    // 实际是BackStackRecord的commitAllowingStateLoss()方法。 mCurTransaction.commitAllowingStateLoss(); mCurTransaction
    = null;
                // 实际是FragmentManagerImpl的execPendingActions()方法。 mFragmentManager.executePendingTransactions(); } }

    backStackRecord.commitAllowingStateLoss():

    public int commitAllowingStateLoss() {
            return commitInternal(true);
        }

    int commitInternal(boolean allowStateLoss) {
            if (mCommitted) throw new IllegalStateException("commit already called");
            if (FragmentManagerImpl.DEBUG) {
                Log.v(TAG, "Commit: " + this);
                LogWriter logw = new LogWriter(TAG);
                PrintWriter pw = new PrintWriter(logw);
                dump("  ", null, pw, null);
            }
            mCommitted = true;
            if (mAddToBackStack) {
                mIndex = mManager.allocBackStackIndex(this);
            } else {
                mIndex = -1;
            }
    // BackStackRecord实现了Runnable接口。
       // 实际是FragmentManagerImpl的enqueueAction()方法。
    mManager.enqueueAction(
    this, allowStateLoss); return mIndex; }
    
    

    fragmentManagerImpl.enqueueAction():

    public void enqueueAction(Runnable action, boolean allowStateLoss) {
            if (!allowStateLoss) {
                checkStateLoss();
            }
            synchronized (this) {
                if (mDestroyed || mHost == null) {
                    throw new IllegalStateException("Activity has been destroyed");
                }
                if (mPendingActions == null) {
                    mPendingActions = new ArrayList<Runnable>();
                }
                // 最终把BackStackRecord实例添加到了mPendingActions(这是一个ArrayList<Runnable>变量)。 mPendingActions.add(action);
    if (mPendingActions.size() == 1) { mHost.getHandler().removeCallbacks(mExecCommit); mHost.getHandler().post(mExecCommit); } } }

    fragmentManagerImpl.executePendingTransaction():

    public boolean executePendingTransactions() {
            return execPendingActions();
        }

    fragmentManagerImpl.executePendingActions():

    public boolean execPendingActions() {
            if (mExecutingActions) {
                throw new IllegalStateException("Recursive entry to executePendingTransactions");
            }
            
            if (Looper.myLooper() != mHost.getHandler().getLooper()) {
                throw new IllegalStateException("Must be called from main thread of process");
            }
    
            boolean didSomething = false;
    
            while (true) {
                int numActions;
                
                synchronized (this) {
                    if (mPendingActions == null || mPendingActions.size() == 0) {
                        break;
                    }
                    
                    numActions = mPendingActions.size();
                    if (mTmpActions == null || mTmpActions.length < numActions) {
                        mTmpActions = new Runnable[numActions];
                    }
                    mPendingActions.toArray(mTmpActions);
                    mPendingActions.clear();
                    mHost.getHandler().removeCallbacks(mExecCommit);
                }
                
                mExecutingActions = true;
                for (int i=0; i<numActions; i++) {
    // 这里最终调用BackStackRecord的run()方法。 mTmpActions[i].run(); mTmpActions[i]
    = null; } mExecutingActions = false; didSomething = true; } if (mHavePendingDeferredStart) { boolean loadersRunning = false; for (int i=0; i<mActive.size(); i++) { Fragment f = mActive.get(i); if (f != null && f.mLoaderManager != null) { loadersRunning |= f.mLoaderManager.hasRunningLoaders(); } } if (!loadersRunning) { mHavePendingDeferredStart = false; startPendingDeferredFragments(); } } return didSomething; }

    backStackRecord.run():

    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);
    
            TransitionState state = null;
            SparseArray<Fragment> firstOutFragments = null;
            SparseArray<Fragment> lastInFragments = null;
            if (SUPPORTS_TRANSITIONS) {
                firstOutFragments = new SparseArray<Fragment>();
                lastInFragments = new SparseArray<Fragment>();
                // 这里。。。
                calculateFragments(firstOutFragments, lastInFragments);
    
                state = beginTransition(firstOutFragments, lastInFragments, false);
            }
    
            int transitionStyle = state != null ? 0 : mTransitionStyle;
            int transition = state != null ? 0 : mTransition;
            Op op = mHead;
            while (op != null) {
                int enterAnim = state != null ? 0 : op.enterAnim;
                int exitAnim = state != null ? 0 : op.exitAnim;
                switch (op.cmd) {
                    case OP_ADD: {
                        Fragment f = op.fragment;
                        f.mNextAnim = enterAnim;
                        mManager.addFragment(f, false);
                    } break;
                    case OP_REPLACE: {
                        Fragment f = op.fragment;
                        int containerId = f.mContainerId;
                        if (mManager.mAdded != null) {
                            for (int i = mManager.mAdded.size() - 1; i >= 0; i--) {
                                Fragment old = mManager.mAdded.get(i);
                                if (FragmentManagerImpl.DEBUG) Log.v(TAG,
                                        "OP_REPLACE: adding=" + f + " old=" + old);
                                if (old.mContainerId == containerId) {
                                    if (old == f) {
                                        op.fragment = f = null;
                                    } else {
                                        if (op.removed == null) {
                                            op.removed = new ArrayList<Fragment>();
                                        }
                                        op.removed.add(old);
                                        old.mNextAnim = exitAnim;
                                        if (mAddToBackStack) {
                                            old.mBackStackNesting += 1;
                                            if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
                                                    + old + " to " + old.mBackStackNesting);
                                        }
                                        mManager.removeFragment(old, transition, transitionStyle);
                                    }
                                }
                            }
                        }
                        if (f != null) {
                            f.mNextAnim = enterAnim;
                            mManager.addFragment(f, false);
                        }
                    } break;
                    case OP_REMOVE: {
                        Fragment f = op.fragment;
                        f.mNextAnim = exitAnim;
                        mManager.removeFragment(f, transition, transitionStyle);
                    } break;
                    case OP_HIDE: {
                        Fragment f = op.fragment;
                        f.mNextAnim = exitAnim;
                        mManager.hideFragment(f, transition, transitionStyle);
                    } break;
                    case OP_SHOW: {
                        Fragment f = op.fragment;
                        f.mNextAnim = enterAnim;
                        mManager.showFragment(f, transition, transitionStyle);
                    } break;
                    case OP_DETACH: {
                        Fragment f = op.fragment;
                        f.mNextAnim = exitAnim;
                        mManager.detachFragment(f, transition, transitionStyle);
                    } break;
                    case OP_ATTACH: {
                        Fragment f = op.fragment;
                        f.mNextAnim = enterAnim;
                        mManager.attachFragment(f, transition, transitionStyle);
                    } break;
                    default: {
                        throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
                    }
                }
    
                op = op.next;
            }
         // 这里添加child
            mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);
    
            if (mAddToBackStack) {
                mManager.addBackStackState(this);
            }
        }

     Fragment的状态最终都是通过moveToState(Fragment, int, int, int, boolean)进行的,而添加和删除child就在其中。

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                boolean keepActive) {
            // Fragments that are not currently added will sit in the onCreate() state.
            if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
                newState = Fragment.CREATED;
            }
            if (f.mRemoving && newState > f.mState) {
                // While removing a fragment, we can't change it to a higher state.
                newState = f.mState;
            }
            // Defer start if requested; don't allow it to move to STARTED or higher
            // if it's not already started.
            if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
                newState = Fragment.STOPPED;
            }
            if (f.mState < newState) {
                // For fragments that are created from a layout, when restoring from
                // state we don't want to allow them to be created until they are
                // being reloaded from the layout.
                if (f.mFromLayout && !f.mInLayout) {
                    return;
                }  
                if (f.mAnimatingAway != null) {
                    // The fragment is currently being animated...  but!  Now we
                    // want to move our state back up.  Give up on waiting for the
                    // animation, move to whatever the final state should be once
                    // the animation is done, and then we can proceed from there.
                    f.mAnimatingAway = null;
                    moveToState(f, f.mStateAfterAnimating, 0, 0, true);
                }
                switch (f.mState) {
                    case Fragment.INITIALIZING:
                        if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                        if (f.mSavedFragmentState != null) {
                            f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                            f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
                                    FragmentManagerImpl.VIEW_STATE_TAG);
                            f.mTarget = getFragment(f.mSavedFragmentState,
                                    FragmentManagerImpl.TARGET_STATE_TAG);
                            if (f.mTarget != null) {
                                f.mTargetRequestCode = f.mSavedFragmentState.getInt(
                                        FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
                            }
                            f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
                                    FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
                            if (!f.mUserVisibleHint) {
                                f.mDeferStart = true;
                                if (newState > Fragment.STOPPED) {
                                    newState = Fragment.STOPPED;
                                }
                            }
                        }
                        f.mHost = mHost;
                        f.mParentFragment = mParent;
                        f.mFragmentManager = mParent != null
                                ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
                        f.mCalled = false;
                        f.onAttach(mHost.getContext());
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onAttach()");
                        }
                        if (f.mParentFragment == null) {
                            mHost.onAttachFragment(f);
                        }
    
                        if (!f.mRetaining) {
                            f.performCreate(f.mSavedFragmentState);
                        }
                        f.mRetaining = false;
                        if (f.mFromLayout) {
                            // For fragments that are part of the content view
                            // layout, we need to instantiate the view immediately
                            // and the inflater will take care of adding it.
                            f.mView = f.performCreateView(f.getLayoutInflater(
                                    f.mSavedFragmentState), null, f.mSavedFragmentState);
                            if (f.mView != null) {
                                f.mInnerView = f.mView;
                                if (Build.VERSION.SDK_INT >= 11) {
                                    ViewCompat.setSaveFromParentEnabled(f.mView, false);
                                } else {
                                    f.mView = NoSaveStateFrameLayout.wrap(f.mView);
                                }
                                if (f.mHidden) f.mView.setVisibility(View.GONE);
                                f.onViewCreated(f.mView, f.mSavedFragmentState);
                            } else {
                                f.mInnerView = null;
                            }
                        }
                    case Fragment.CREATED:
                        if (newState > Fragment.CREATED) {
                            if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
                            if (!f.mFromLayout) {
                                ViewGroup container = null;
                                if (f.mContainerId != 0) {
                                    container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
                                    if (container == null && !f.mRestored) {
                                        throwException(new IllegalArgumentException(
                                                "No view found for id 0x"
                                                + Integer.toHexString(f.mContainerId) + " ("
                                                + f.getResources().getResourceName(f.mContainerId)
                                                + ") for fragment " + f));
                                    }
                                }
                                f.mContainer = container;
    // 这里面会调用onCreateView()。 f.mView
    = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), container, f.mSavedFragmentState); if (f.mView != null) { f.mInnerView = f.mView; if (Build.VERSION.SDK_INT >= 11) { ViewCompat.setSaveFromParentEnabled(f.mView, false); } else { f.mView = NoSaveStateFrameLayout.wrap(f.mView); } if (container != null) { Animation anim = loadAnimation(f, transit, true, transitionStyle); if (anim != null) { setHWLayerAnimListenerIfAlpha(f.mView, anim); f.mView.startAnimation(anim); }
    // 添加child在这里哦。。。 container.addView(f.mView); }
    if (f.mHidden) f.mView.setVisibility(View.GONE); f.onViewCreated(f.mView, f.mSavedFragmentState); } else { f.mInnerView = null; } } f.performActivityCreated(f.mSavedFragmentState); if (f.mView != null) { f.restoreViewState(f.mSavedFragmentState); } f.mSavedFragmentState = null; } case Fragment.ACTIVITY_CREATED: case Fragment.STOPPED: if (newState > Fragment.STOPPED) { if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); f.performStart(); } case Fragment.STARTED: if (newState > Fragment.STARTED) { if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f); f.performResume(); f.mSavedFragmentState = null; f.mSavedViewState = null; } } } else if (f.mState > newState) { switch (f.mState) { case Fragment.RESUMED: if (newState < Fragment.RESUMED) { if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f); f.performPause(); } case Fragment.STARTED: if (newState < Fragment.STARTED) { if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f); f.performStop(); } case Fragment.STOPPED: if (newState < Fragment.STOPPED) { if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f); f.performReallyStop(); } case Fragment.ACTIVITY_CREATED: if (newState < Fragment.ACTIVITY_CREATED) { if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f); if (f.mView != null) { // Need to save the current view state if not // done already. if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) { saveFragmentViewState(f); } }
    // 这里面会调用onDestroyView()。 f.performDestroyView();
    if (f.mView != null && f.mContainer != null) { Animation anim = null; if (mCurState > Fragment.INITIALIZING && !mDestroyed) { anim = loadAnimation(f, transit, false, transitionStyle); } if (anim != null) { final Fragment fragment = f; f.mAnimatingAway = f.mView; f.mStateAfterAnimating = newState; final View viewToAnimate = f.mView; anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener( viewToAnimate, anim) { @Override public void onAnimationEnd(Animation animation) { super.onAnimationEnd(animation); if (fragment.mAnimatingAway != null) { fragment.mAnimatingAway = null; moveToState(fragment, fragment.mStateAfterAnimating, 0, 0, false); } } }); f.mView.startAnimation(anim); }
    // 删除child在这里哦。。。 f.mContainer.removeView(f.mView); } f.mContainer
    = null; f.mView = null; f.mInnerView = null; } case Fragment.CREATED: if (newState < Fragment.CREATED) { if (mDestroyed) { if (f.mAnimatingAway != null) { // The fragment's containing activity is // being destroyed, but this fragment is // currently animating away. Stop the // animation right now -- it is not needed, // and we can't wait any more on destroying // the fragment. View v = f.mAnimatingAway; f.mAnimatingAway = null; v.clearAnimation(); } } if (f.mAnimatingAway != null) { // We are waiting for the fragment's view to finish // animating away. Just make a note of the state // the fragment now should move to once the animation // is done. f.mStateAfterAnimating = newState; newState = Fragment.CREATED; } else { if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f); if (!f.mRetaining) { f.performDestroy(); } else { f.mState = Fragment.INITIALIZING; } f.mCalled = false; f.onDetach(); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onDetach()"); } if (!keepActive) { if (!f.mRetaining) { makeInactive(f); } else { f.mHost = null; f.mParentFragment = null; f.mFragmentManager = null; f.mChildFragmentManager = null; } } } } } } if (f.mState != newState) { Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; " + "expected state " + newState + " found " + f.mState); f.mState = newState; } }

    在onCreateView()之后,完成child添加;在onDestroyView()之后,完成child删除。

    无论怎样,Fragment状态的变更都是在moveToState函数中完成的,因此Fragment对应的View添加到其他ViewGroup中或者从ViewGroup中移出,都是从moveToState开始的。

  • 相关阅读:
    值得收藏的14款响应式前端开发框架
    简单几步把LOGO变字体
    7 款免费的 Metro UI 模板
    JPG渐进 & PNG/PNG24 交错测试
    你的钱,以后是放银行还是放支付宝?
    Bise IE6 在你的网站上加上它让IE滚蛋吧
    单例模式常见场景
    10 个最新的开发者工具
    大流量网站的底层系统架构
    DNS解析全过程及原理
  • 原文地址:https://www.cnblogs.com/yarightok/p/5674508.html
Copyright © 2020-2023  润新知