Fragment FragmentManager Fragmen

2018-03-02  本文已影响0人  AndrLin

Fragment相关类的关系及说明

UML类图

UML类关系图
上图虽然不是Fragment工作过程中所有类,但是也能表达Fragment工作过程中主要类的关系。下面对一些类进行简要的说明。

相关类说明

Fragment生命周期

想要了解Fragment生命周期,当然是进入FragmentActivity了,因为Fragment生命周期和Activity生命周期息息相关嘛。

进入FragmentActivity直接搜索Fragment,首先我们可以找到一个叫mFragments的常量:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

再接着搜索,可以在FragmentActivity相关生命周期方法中找到mFragments的使用:

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        mFragments.dispatchCreate();
    }
    ...// 这里只展示一个,其他生命周期方法类同

至此,我们可以知道Fragment的生命周期为什么和Activity生命周期息息相关了。接着我们再看看mFragments也就是FragmentController中相关方法:

private final FragmentHostCallback<?> mHost;
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
        return new FragmentController(callbacks);
    }

    private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
    }

public void dispatchStart() {
        mHost.mFragmentManager.dispatchStart();
    }

FragmentController相关方法其内部调用的FragmentManager的方法,跟踪代码发现,首先会进入moveToState(int newState, boolean always)方法中,在其中会遍历所以已添加和处于活动中的Fragment进行下一步处理:

void moveToState(int newState, boolean always) {
        ...

        if (mActive != null) {
            boolean loadersRunning = false;

            // Must add them in the proper order. mActive fragments may be out of order
            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.valueAt(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;
            }
        }
    }

然后进入moveFragmentToExpectedState()方法中,首先会进入moveToState(Fragment,newState,transit,transitionStyle,keepActive)方法中进行状态分发,根据不同的状态进行处理相应的逻辑,例如在Create状态将View添加到ActivityViewGroup中等;然后进行View的移动,确保FragmentView以正确的顺序显示;最后执行动画:

void moveFragmentToExpectedState(Fragment f) {
        if (f == null) {
            return;
        }
        int nextState = mCurState;
        if (f.mRemoving) {
            if (f.isInBackStack()) {
                nextState = Math.min(nextState, Fragment.CREATED);
            } else {
                nextState = Math.min(nextState, Fragment.INITIALIZING);
            }
        }
        // 第一步:根据不同状态进行分发
        moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);

        if (f.mView != null) {
            // 第二步:移动View在Activity的ViewGroup中的显示顺序
            // Move the view if it is out of order
            Fragment underFragment = findFragmentUnder(f);
            if (underFragment != null) {
                final View underView = underFragment.mView;
                // make sure this fragment is in the right order.
                final ViewGroup container = f.mContainer;
                int underIndex = container.indexOfChild(underView);
                int viewIndex = container.indexOfChild(f.mView);
                if (viewIndex < underIndex) {
                    container.removeViewAt(viewIndex);
                    container.addView(f.mView, underIndex);
                }
            }
            // 第三步:新添加的Fragment,执行动画
            if (f.mIsNewlyAdded && f.mContainer != null) {
                // Make it visible and run the animations
                if (f.mPostponedAlpha > 0f) {
                    f.mView.setAlpha(f.mPostponedAlpha);
                }
                f.mPostponedAlpha = 0f;
                f.mIsNewlyAdded = false;
                // run animations:
                AnimationOrAnimator anim = loadAnimation(f, f.getNextTransition(), true,
                        f.getNextTransitionStyle());
                if (anim != null) {
                    setHWLayerAnimListenerIfAlpha(f.mView, anim);
                    if (anim.animation != null) {
                        f.mView.startAnimation(anim.animation);
                    } else {
                        anim.animator.setTarget(f.mView);
                        anim.animator.start();
                    }
                }
            }
        }
        // 第四步:判断Fragment显示隐藏是否改变,如改变,则在completeShowHideFragment中执行动画
        if (f.mHiddenChanged) {
            completeShowHideFragment(f);
        }
    }

以上是Activity生命周期触发Fragment生命周期的过程,至于动态添加Fragment,实际上最终也是到moveToState(Fragment,newState,transit,transitionStyle,keepActive)中根据状态进行处理。

Fragment事务

在开发中,我们通常都是使用事务来操作Fragment的添加、显示、隐藏的,那么其内部是如何处理的呢?

首先,我们来看下add()hide()show()replace()方法中是如何处理的。进入BackStackRecord类查看代码发现,它们都调用了doAddOp()方法:

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        ...// 省略其他内容
        addOp(new Op(opcmd, fragment));
    }

doAddOp()方法最终会创建一个Op()对象,并添加到集合中保存。Op类我们在开始的时候说过,主要是用来存储Fragment操作类型的,也就是cmd,它的可选参数有:

static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
static final int OP_DETACH = 6;
static final int OP_ATTACH = 7;
static final int OP_SET_PRIMARY_NAV = 8;
static final int OP_UNSET_PRIMARY_NAV = 9;

通过上面查看代码,我们可以发现:开启事务后我们进行的add()hide()等操作都会以Op()对象的形式存储在集合中。接下来我们看看最后我们所调用的commit()又做了些什么?

查看commit()方法发现其调用的是commitInternal()方法:

int commitInternal(boolean allowStateLoss) {
        ...//省略部分代码
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

在其中调用的是FragmentManagerenqueueAction()方法,会将当前BackStackRecord实例传入其中:

public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                if (allowStateLoss) {
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<>();
            }
            mPendingActions.add(action);
            scheduleCommit();
        }
    }

enqueueAction方法中,将action排入队列,最后调用scheduleCommit()方法:

private void scheduleCommit() {
        synchronized (this) {
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
            boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
            }
        }
    }

Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };

查看代码发现,最后调用的是FragmentHostCallbackHandler进行异步操作,此Handler实际上是FragmentActivity的。

跟踪代码发现execPendingActions()方法最后会调用BackStackRecordexecutePopOps()executeOps()方法来处理具体的操作:

    void executePopOps(boolean moveToState) {
        for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
            final Op op = mOps.get(opNum);
            Fragment f = op.fragment;
            if (f != null) {
                f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
                        mTransitionStyle);
            }
            //根据Op类型,调用FragmentManager相关方法,改变Fragment状态
            switch (op.cmd) {
                case OP_ADD:
                    f.setNextAnim(op.popExitAnim);
                    mManager.removeFragment(f);
                    break;
                case OP_REMOVE:
                    f.setNextAnim(op.popEnterAnim);
                    mManager.addFragment(f, false);
                    break;
                case OP_HIDE:
                    f.setNextAnim(op.popEnterAnim);
                    mManager.showFragment(f);
                    break;
                case OP_SHOW:
                    f.setNextAnim(op.popExitAnim);
                    mManager.hideFragment(f);
                    break;
                case OP_DETACH:
                    f.setNextAnim(op.popEnterAnim);
                    mManager.attachFragment(f);
                    break;
                case OP_ATTACH:
                    f.setNextAnim(op.popExitAnim);
                    mManager.detachFragment(f);
                    break;
                case OP_SET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(null);
                    break;
                case OP_UNSET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(f);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
            }
            if (!mReorderingAllowed && op.cmd != OP_REMOVE && f != null) {
            // 上面讲生命周期的时候有相应描述
                mManager.moveFragmentToExpectedState(f);
            }
        }
        if (!mReorderingAllowed && moveToState) {
           // 上面讲生命周期的时候有相应描述
            mManager.moveToState(mManager.mCurState, true);
        }
    }

总结

Fragment相关代码较多,以上也只是一点粗陋的分析,接下来的路还很漫长。

image
上一篇 下一篇

猜你喜欢

热点阅读