美文网首页
Fragment 的生命周期来龙去脉

Fragment 的生命周期来龙去脉

作者: jfson_土豆 | 来源:发表于2017-11-06 18:20 被阅读102次

    Fragment的生命周期我们都不陌生,但是其如何利用FragmentManager从Activity生命周期挂载而来的呢,尤其是看了glide源码后,发现其巧妙的利用了FragmentManager来绑定自己的生命周期,那么为了更清晰的深入理解,一起来看下6.0的源码是如何处理的。

    FragmentActivity

    • 1.从启动一个FragmentActivity开始。从onCreate()方法中
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);
        super.onCreate(savedInstanceState);
    
        NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            mFragments.restoreLoaderNonConfig(nc.loaders);
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
        }
        mFragments.dispatchCreate();
    }
    
    • 1.1 重点关注一下 mFragments 的操作。当前的mFragments其实是FragmentController,而FragmentHostCallback在FragmentController初始化时进行初始化,在FragmentHostCallback中可以拿到FragmentManager的子类FragmentManagerImpl。继续看FragmentController的代码
    //FragmentController初始化CallBack
     public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
            return new FragmentController(callbacks);
    }
    
    private FragmentController(FragmentHostCallback<?> callbacks) {
            mHost = callbacks;
    }
        
    public void attachHost(Fragment parent) {
            mHost.mFragmentManager.attachController(
                    mHost, mHost /*container*/, parent);
    }
        
    public void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
            mHost.mFragmentManager.restoreAllState(state, nonConfig);
    }
        
    public void dispatchCreate() {
            mHost.mFragmentManager.dispatchCreate();
    }
    
    • 1.2当前的操作其实都是对FragmentManager进行操作,继续看FragmentManagerImpl代码
    // 初始化赋值操作
    public void attachController(FragmentHostCallback host,
                FragmentContainer container, Fragment parent) {
            if (mHost != null) throw new IllegalStateException("Already attached");
            mHost = host;
            mContainer = container;
            mParent = parent;
    }
    
    void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
        ......
        if (nonConfig != null) {
                List<Fragment> nonConfigFragments = nonConfig.getFragments();
                childNonConfigs = nonConfig.getChildNonConfigs();
                final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
                for (int i = 0; i < count; i++) {
                    Fragment f = nonConfigFragments.get(i);
                    if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
                    FragmentState fs = fms.mActive[f.mIndex];
                    fs.mInstance = f;
                    f.mSavedViewState = null;
                    f.mBackStackNesting = 0;
                    f.mInLayout = false;
                    f.mAdded = false;
                    f.mTarget = null;
                    if (fs.mSavedFragmentState != null) {
                        fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                        f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
                                FragmentManagerImpl.VIEW_STATE_TAG);
                        f.mSavedFragmentState = fs.mSavedFragmentState;
                    }
                }
            }
        
        
            // Build the full list of active fragments, instantiating them from
            // their saved state.
            mActive = new ArrayList<>(fms.mActive.length); 
            // 注意,后面会用到
        ...
    }
    
    public void dispatchCreate() {
            mStateSaved = false;
            mExecutingActions = true;
            moveToState(Fragment.CREATED, false);
            mExecutingActions = false;
    }
    
    
    • 1.3 以上,attachController() 只是简单的初始化的赋值操作,并无对生命周期相关的,继续看restoreAllState(),同样的初始化的重置操作,这里
      mActive = new ArrayList<Fragment>(fms.mActive.length)初始化了一个空的mActive的list。继续看dispatchCreate(),其中moveToState
        void moveToState(int newState, boolean always) {
            if (mHost == null && newState != Fragment.INITIALIZING) {
                throw new IllegalStateException("No activity");
            }
    
            if (!always && newState == mCurState) {
                return;
            }
    
            mCurState = newState;
    
            if (mActive != null) {
                boolean loadersRunning = false;
    
                // Must add them in the proper order. mActive fragments may be out of order
                if (mAdded != null) {
                    final int numAdded = mAdded.size();
                    for (int i = 0; i < numAdded; i++) {
                        Fragment f = mAdded.get(i);
                        moveFragmentToExpectedState(f);
                        if (f.mLoaderManager != null) {
                            loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                        }
                    }
                }
    
                // Now iterate through all active fragments. These will include those that are removed
                // and detached.
                final int numActive = mActive.size();
                for (int i = 0; i < numActive; i++) {
                    Fragment f = mActive.get(i);
                    if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                        moveFragmentToExpectedState(f);
                        if (f.mLoaderManager != null) {
                            loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                        }
                    }
                }
    
                if (!loadersRunning) {
                    startPendingDeferredFragments();
                }
    
                if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
                    mHost.onSupportInvalidateOptionsMenu();
                    mNeedMenuInvalidate = false;
                }
            }
        }
    
    • 1.4 moveToState() 其实是更新FragmentManager的状态至Fragment,但是当前并无Fragment,mActive在restoreAllState()初始化出来后只是个空的list,因此并没有实质的操作。至此FragmentActivity onCreate()都是初始化的操作。

    • 2 Fragment的真正启动是当我们调用FragmentManager.beginTransaction().add(fragmet).commit()时触发。看下代码

    public abstract class FragmentTransaction {
        ......
        public abstract int commit();
    
        /**
         * Calls {@link #add(int, Fragment, String)} with a 0 containerViewId.
         */
        public abstract FragmentTransaction add(Fragment fragment, String tag);
        
        /**
         * Calls {@link #add(int, Fragment, String)} with a null tag.
         */
        public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);
        
        public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment,
                @Nullable String tag);
        ......
        }
    
    • 2.1 抽象类FragmentTransaction,这里有个add(Fragment fragment, String tag)方法,添加一个Fragment,只设置tag,不设置viewId,说白了添加一个不妨碍业务的空Fragment方法,这是glide的绑定生命周期的一个点。继续看实现类
    final class BackStackRecord extends FragmentTransaction implements
            FragmentManager.BackStackEntry, Runnable {
        ...
         public FragmentTransaction add(int containerViewId, Fragment fragment) {
            doAddOp(containerViewId, fragment, null, OP_ADD);
            return this;
        }
        
        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);
        }
        
         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++;
        }
        
        public int commit() {
            return commitInternal(false);
        }
    
        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;
            }
            mManager.enqueueAction(this, allowStateLoss);
            return mIndex;
        }
        ...
    }
    
    • 2.2 先看add(),在实现类中调用到了doAddOp(),而在doAddOp方法内去对当前的Fragment进栈操作,这里OP_ADD为op.cmd = opcmd;的赋值,对应的操作如下,mManager.addFragment(f, false)很明显添加一个Fragment。并break;
    public void run() {
            ...
            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: {
                        ...
                        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;
            }
    
            mManager.moveToState(mManager.mCurState, transition, transitionStyle, 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);
                }
            }
        }
    
    • 2.3 最后肯定是走到moveToState(fragment);moveToState(fragment)这个方法很重要,break后走这里,这个方法一会继续看,我们顺带看一下其他的commit()操作。当前BackStackRecord实现类中的mManager是FragmentManagerImpl。这就很好理解了,又转到了熟悉的FragmentManagerImpl中了,继续看代码。
    
    mManager.enqueueAction(this, allowStateLoss);
    
    final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory {
     /**
         * Adds an action to the queue of pending actions.
         *
         * @param action the action to add
         * @param allowStateLoss whether to allow loss of state information
         * @throws IllegalStateException if the activity has been destroyed
         */
        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>();
                }
                mPendingActions.add(action);
                if (mPendingActions.size() == 1) {
                    mHost.getHandler().removeCallbacks(mExecCommit);
                    mHost.getHandler().post(mExecCommit);
                }
            }
        }
    
    Runnable mExecCommit = new Runnable() {
            @Override
            public void run() {
                execPendingActions();
            }
        };
    }
    
    • 2.4 在 mPendingActions.add(action)中,mPendingActions为action的list,添加一个事件,如果是第一个,发送消息mHost.getHandler().post(mExecCommit),继续看mExecCommit消息就走到了execPendingActions(),上代码看下
        /**
         * Only call from main thread!
         */
        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++) {
                    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;
        }
        
    
    • 2.5 这里关注startPendingDeferredFragments()就可以了
    void startPendingDeferredFragments() {
            if (mActive == null) return;
    
            for (int i=0; i<mActive.size(); i++) {
                Fragment f = mActive.get(i);
                if (f != null) {
                    performPendingDeferredStart(f);
                }
            }
    }
    
    public void performPendingDeferredStart(Fragment f) {
            if (f.mDeferStart) {
                if (mExecutingActions) {
                    // Wait until we're done executing our pending transactions
                    mHavePendingDeferredStart = true;
                    return;
                }
                f.mDeferStart = false;
                moveToState(f, mCurState, 0, 0, false);
            }
        }
    
    • 2.6 重点来了,最后我们可以看到ragmentManager.beginTransaction().add(fragmet).commit()的操作,commit最终调用到了moveToState()。也走到了这里
    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                boolean keepActive) {
                
        if (f.mState < newState) {
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    ...
                    f.mHost = mHost;
                    f.mParentFragment = mParent;
                    f.mFragmentManager = mParent != null
                            ? mParent.mChildFragmentManager :mHost.getFragmentManagerImpl();
                    f.mCalled = false;
                    f.onAttach(mHost.getContext());
                    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 (f.mHidden) f.mView.setVisibility(View.GONE);
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                                ...
                        }
                    }
                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);
                                }
                                f.mContainer = container;
                                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);
                                        }
                                        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.mResumed = true;
                            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();
                            f.mResumed = false;
                        }
                    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);
                                }
                            }
                            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);
                                }
                                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();
                                }
    
                                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;
                                    }
                                }
                            }
                        }
                }            
    
    • 3.moveToState()代码有点多,精简一下
    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                         boolean keepActive) {
            if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
                newState = Fragment.CREATED;
            }
            if (f.mRemoving && newState > f.mState) {
                newState = f.mState;
            }
            if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
                newState = Fragment.STOPPED;
            }
            if (f.mState < newState) {
                switch (f.mState) {
                    case Fragment.INITIALIZING:
                        f.onAttach(mHost.getContext());
                        mHost.onAttachFragment(f);
                        f.onViewCreated(f.mView, f.mSavedFragmentState);
                    case Fragment.CREATED:
                        container.addView(f.mView);
                        f.onViewCreated(f.mView, f.mSavedFragmentState);
                        f.performActivityCreated(f.mSavedFragmentState);
                        f.restoreViewState(f.mSavedFragmentState);
    
                    case Fragment.ACTIVITY_CREATED:
                    case Fragment.STOPPED:
                        f.performStart();
                    case Fragment.STARTED:
                        f.performResume();
                }
            } else if (f.mState > newState) {
                switch (f.mState) {
                    case Fragment.RESUMED:
                        if (newState < Fragment.RESUMED) {
                            f.performPause();
                        }
                    case Fragment.STARTED:
                        if (newState < Fragment.STARTED) {
                            f.performStop();
                        }
                    case Fragment.STOPPED:
                        if (newState < Fragment.STOPPED) {
                            f.performReallyStop();
                        }
                    case Fragment.ACTIVITY_CREATED:
                        if (newState < Fragment.ACTIVITY_CREATED) {
                            f.performDestroyView();
                        }
                    case Fragment.CREATED:
                        if (newState < Fragment.CREATED) {
                            if (f.mAnimatingAway != null) {
                                newState = Fragment.CREATED;
                            } else {
                                f.performDestroy();
                                f.mCalled = false;
                                f.onDetach();
                            }
                        }
                }
            }
        }
    
    public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener {
        static final int INITIALIZING = 0;     // Not yet created.
        static final int CREATED = 1;          // Created.
        static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
        static final int STOPPED = 3;          // Fully created, not started.
        static final int STARTED = 4;          // Created and started, not resumed.
        static final int RESUMED = 5;          // Created started and resumed.
    }
    
    • 3.1 当前switch的各个case并没有break;这里有个
      mCurState = newState;对mCurState的赋值操作
      当FragmentActivity启动后,newState已经是Fragment.RESUMED了。所以现在是f.mState = Fragment.INITIALIZING,newState = RESUMED;根据switch中的case依次走了Fragment的创建的生命周期。

    • 4 销毁过程同理了,还是在moveToState()。依次来看

    • 4.1 getFragmentManager().beginTransaction().remove(fragment()).commit();

    FragmentTransaction{
        public abstract FragmentTransaction remove(Fragment var1)
    }
    
    BackStackRecord{
        public FragmentTransaction remove(Fragment fragment) {
            Op op = new Op();
            op.cmd = OP_REMOVE; 
            op.fragment = fragment;
            addOp(op);
    
            return this;
        }
    }
    
    
    • 4.2 这里op.cmd = OP_REMOVE下面会用到,还是开始的run()内,可以看到add()也是在这里进行操作。remove也一样:mManager.removeFragment();
    public void run() {
            ...
            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: {
                        ...
                        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;
            }
    
            mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);
            ...
        }
        
         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;
                }
                fragment.mAdded = false;
                fragment.mRemoving = true;
                moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                        transition, transitionStyle, false);
            }
        }
    
    • 走进moveToState,else if (f.mState > newState) {}这里依次进行生命周期调用。
    • 所以你看。绑定最重要的看懂moveToState就好咯。

    相关文章

      网友评论

          本文标题:Fragment 的生命周期来龙去脉

          本文链接:https://www.haomeiwen.com/subject/ylzlmxtx.html