Fragment 分析

先来看看 Fragment 的用法:

  Fragment fragment = new Fragment();
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.fragment_container, fragment);
        transaction.commit();

然后一步步分析代码。

Activity.getFragmentManager()

 public FragmentManager getFragmentManager() {
        return mFragments.getFragmentManager();
    }

接下来看看mFragments是什么?

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

mFragments是 Activity 的一个成员变量,构造它时,传入了一个HostCallbacks对象,先看FragmentController类。

public class FragmentController {
    private final FragmentHostCallback<?> mHost;

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

    private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
    }
  //*************省略部分代码**********
}

而传入的HostCallbacks是 Activity 的一个内部类。

 class HostCallbacks extends FragmentHostCallback<Activity> {
        public HostCallbacks() {
            super(Activity.this );
        }
        //*************省略部分代码**********
    }

看看HostCallbacks的父类FragmentHostCallback构造方法做什么了

public abstract class FragmentHostCallback<E> extends FragmentContainer {

    FragmentHostCallback(Activity activity) {
        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
    }

    FragmentHostCallback(Activity activity, Context context, Handler handler,
            int windowAnimations) {
        mActivity = activity;
        mContext = context;
        mHandler = handler;
        mWindowAnimations = windowAnimations;
    }
  //*************省略部分代码**********
}

由此可见,mFragments通过构造时传入HostCallbacks对象,从而持有了当前 Activity 的引用,并且还持有当前 Activity 的mHandler对象。

再加到mFragments.getFragmentManager()中去.

FragmentController.getFragmentManager()

 public FragmentManager getFragmentManager() {
        return mHost.getFragmentManagerImpl();
    }

mHost对象就是刚刚的HostCallbacks,getFragmentManagerImpl的实现在HostCallbacks的父类FragmentHostCallback中

public abstract class FragmentHostCallback<E> extends FragmentContainer {

final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

FragmentManagerImpl getFragmentManagerImpl() {
        return mFragmentManager;
    }
      //*************省略部分代码**********
}

FragmentManagerImpl是FragmentManager的内部类,同时它还是FragmentManager的实现类。接下来看FragmentManager.beginTransaction(),直接看FragmentManager的实现类FragmentManagerImpl。

FragmentManagerImpl.beginTransaction()

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

先看看BackStackRecord的构造方法

final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, Runnable {
 final FragmentManagerImpl mManager

    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;
   Op mHead;
   Op mTail;
    static final class Op {
        Op next;
        Op prev;
        int cmd;
        Fragment fragment;
        int enterAnim;
        int exitAnim;
        int popEnterAnim;
        int popExitAnim;
        ArrayList<Fragment> removed;
    }
 public BackStackRecord(FragmentManagerImpl manager) {
        mManager = manager;
    }
          //*************省略部分代码**********
}

可见,构造BackStackRecord时将FragmentManagerImpl(即:FragmentManager)传进来了。而BackStackRecord继承了FragmentTransaction并实现了Runnable接口。更重要的是BackStackRecord有一个名为Op的内部类,Op实现非常简单,就是一个双向链表的实现。
看完FragmentManager.beginTransaction(),接着看FragmentTransaction.add(R.id.fragment_container, fragment),直接看BackStackRecord即可;

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

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

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

BackStackRecord有三个重载的 add 方法,最终都调用了doAddOp。

BackStackRecord.doAddOp(…)

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
       //将mManager的值赋给Fragment的mFragmentManager对象
        fragment.mFragmentManager = mManager;
       //对于同一个Fragment实例,变量 mTag 的值一旦赋予了,就不能改变了
        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;
        }

       //对于同一个Fragment实例,containerViewId也是不能改变的。
        if (containerViewId != 0) {
            if (containerViewId == View.NO_ID) {
                throw new IllegalArgumentException("Can't add fragment "
                        + fragment + " with tag " + tag + " to container view with no id");
            }
            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_ADD)并将 Fragment 存起来,调用addOp()
        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++;
    }

addOp的操作比较简单,就是将新增的 Op对象加到当前的双向链表。其实FragmentTransaction的其它操作(repalce ,remove,sow,hide….)都是类似的,只是传入的操作类型不一样(即 Op.cmd)。接着看FragmentTransaction.commit()函数。

BackStackRecord.commit()

 public int commit() {
        return commitInternal(false);
    }

commit()调用了commitInternal(false),传入的 boolean 值代表着是否允许状态丢失。另外一个commitAllowingStateLoss()方法调用的也是commitInternal,不过传入的是 true 而已。

   int commitInternal(boolean allowStateLoss) {
   //一个事务,只能提交一次
        if (mCommitted) {
            throw new IllegalStateException("commit already called");
        }
      //*************省略部分代码**********
        mCommitted = true;
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        //又到了 FragmentManager 中了
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

FragmentManager.enqueueAction

  public void enqueueAction(Runnable action, boolean allowStateLoss) {
        //如果不允许状态丢失,就进行状态检查,而检查的逻辑很简单:如果 此操作是在Activity的onSaveInstanceState调用了之后,onCreate 之前调用了,就报错
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<Runnable>();
            }
            //将BackStackRecord加入一个ArrayList中
            mPendingActions.add(action);
            //如果是mPendingActions中只有当前的BackStackRecord,即mPendingActions之前是空的,则通过 Activity 的 Handler 发送一条消息,而mExecCommit是一个Runnable对象,它的 run 方法将被调用。 
            if (mPendingActions.size() == 1) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
            }
        }
    }
  Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };
    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) {
            //刚刚的BackStackRecord对象加入到了mPendingActions中
                if (mPendingActions == null || mPendingActions.size() == 0) {
                    break;
                }
                //下面的逻辑很简单,就是从mPendingActions取出BackStackRecord,并调用它的 run 方法(之前已经提过BackStackRecord实现了 Runnable)
                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;
        }

        doPendingDeferredStart();

        return didSomething;
    }

又回到了BackStackRecord中了,看看BackStackRecord的 run方法。

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);

        if (mManager.mCurState >= Fragment.CREATED) {
            SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
            SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
            calculateFragments(firstOutFragments, lastInFragments);
            beginTransition(firstOutFragments, lastInFragments, false);
        }

        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: {
                //Remove与 Add的结合体
                    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);
                            }
                            //必须是同一个 ContainerView
                            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 = 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;
                case OP_REMOVE: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.exitAnim;
                    mManager.removeFragment(f, mTransition, mTransitionStyle);
                }
                break;
                case OP_HIDE: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.exitAnim;
                    mManager.hideFragment(f, mTransition, mTransitionStyle);
                }
                break;
                case OP_SHOW: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    mManager.showFragment(f, mTransition, mTransitionStyle);
                }
                break;
                case OP_DETACH: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.exitAnim;
                    mManager.detachFragment(f, mTransition, mTransitionStyle);
                }
                break;
                case OP_ATTACH: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    mManager.attachFragment(f, mTransition, mTransitionStyle);
                }
                break;
                default: {
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
                }
            }

            op = op.next;
        }

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

      //是否加入回退栈中,其实是加入FragmentManger的一个名为mBackStack的 ArrayList中管理。
        if (mAddToBackStack) {
            mManager.addBackStackState(this);
        }
    }

run方法对刚刚创建的双向链表进行操作,将刚刚加进去的操作一个个执行,最终的执行工作都交给了mManager对象,以 ADD 为例,最终是调用了 mManager.addFragment(f, false)。

FragmentManger.addFragment(…)

    public void addFragment(Fragment fragment, boolean moveToStateNow) {
        if (mAdded == null) {
            mAdded = new ArrayList<Fragment>();
        }
        //将 Fragment中加入到一个名为mActive的ArrayList中进行管理
        makeActive(fragment);
        if (!fragment.mDetached) {
            if (mAdded.contains(fragment)) {
                throw new IllegalStateException("Fragment already added: " + fragment);
            }
            //设置一些状态,加入到一个名为mAdded的ArrayList中进行管理
            mAdded.add(fragment);
            fragment.mAdded = true;
            fragment.mRemoving = false;
            //是否支持菜单栏
            if (fragment.mHasMenu && fragment.mMenuVisible) {
                mNeedMenuInvalidate = true;
            }
            //刚刚传进来的moveToStateNow是 false,那什么时候执行呢 moveToState(fragment)?
            //其实刚刚BackStackRecord 的 run 方法最后调用了 mManager.moveToState(mManager.mCurState, mTransition,mTransitionStyle, true)。
            if (moveToStateNow) {
                moveToState(fragment);
            }
        }
    }

而不管那个moveToState方法,最终都会调用moveToState(int newState, int transit, int transitStyle, boolean always, boolean keepActive)这个有5个参数的方法中去。

FragmentManger.moveToState(…)

 void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
         //****************省略部分代码****************
        //生命周期的正序(onAttach--->onCreate)
        if (f.mState < newState) {
         //****************省略部分代码****************
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                    if (f.mSavedFragmentState != null) {
                        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;
                            }
                        }
                    }
                    //将 FragmentHostCallback<Activity> 设置给 Fragment的 mHost
                    f.mHost = mHost;
                    //如果是 Activity中的 Fragment 则mParent为 null
                    f.mParentFragment = mParent;
                    //设置FragmentManager
                    f.mFragmentManager = mParent != null
                            ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
                    f.mCalled = false;
                    //调用  Fragment的onAttach()方法
                    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);
                    } else {
                        f.mParentFragment.onAttachFragment(f);
                    }

                    if (!f.mRetaining) {
                        //调用  Fragment的onCreate()方法
                        f.performCreate(f.mSavedFragmentState);
                    } else {
                        f.restoreChildFragmentState(f.mSavedFragmentState, true);
                        f.mState = Fragment.CREATED;
                    }
                    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.mView.setSaveFromParentEnabled(false);
                            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) {
                                if (f.mContainerId == View.NO_ID) {
                                    throwException(new IllegalArgumentException(
                                            "Cannot create fragment "
                                                    + f
                                                    + " for a container view with no id"));
                                }
                                container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
                                if (container == null && !f.mRestored) {
                                    String resName;
                                    try {
                                        resName = f.getResources().getResourceName(f.mContainerId);
                                    } catch (NotFoundException e) {
                                        resName = "unknown";
                                    }
                                    throwException(new IllegalArgumentException(
                                            "No view found for id 0x"
                                            + Integer.toHexString(f.mContainerId) + " ("
                                            + resName
                                            + ") for fragment " + f));
                                }
                            }
                            f.mContainer = container;
                            f.mView = f.performCreateView(f.getLayoutInflater(
                                    f.mSavedFragmentState), container, f.mSavedFragmentState);
                            if (f.mView != null) {
                                f.mView.setSaveFromParentEnabled(false);
                                if (container != null) {
                                    Animator anim = loadAnimator(f, transit, true,
                                            transitionStyle);
                                    if (anim != null) {
                                        anim.setTarget(f.mView);
                                        setHWLayerAnimListenerIfAlpha(f.mView, anim);
                                        anim.start();
                                    }
                                    container.addView(f.mView);
                                }
                                if (f.mHidden) f.mView.setVisibility(View.GONE);
                                f.onViewCreated(f.mView, f.mSavedFragmentState);
                            }
                        }

                        f.performActivityCreated(f.mSavedFragmentState);
                        if (f.mView != null) {
                            f.restoreViewState(f.mSavedFragmentState);
                        }
                        f.mSavedFragmentState = null;
                    }
                case Fragment.ACTIVITY_CREATED:
                    if (newState > Fragment.ACTIVITY_CREATED) {
                        f.mState = Fragment.STOPPED;
                    }
                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();
                        // Get rid of this in case we saved it and never needed it.
                        f.mSavedFragmentState = null;
                        f.mSavedViewState = null;
                    }
            }
        } 
        //Fragment 再次加到前台,生命周期的逆序
        else if (f.mState > newState) {
         //****************省略部分代码****************
        }

    }

moveToState方法特别的长,其实就是根据 Fragmenti当着的状态值去更新相应的状态,也就是管理着 Fragment 的生命周期。Activity通过 FragmentManager 将自己的生命周期与 Fragment 同步,最终也都会调用 moveToState。

Fragment.startActivity()

无论是startActivity还是startActivityForResult,最终都会调用FragmentActivity的startActivityFromFragment

public class FragmentActivity extends BaseFragmentActivityHoneycomb implements
        ActivityCompat.OnRequestPermissionsResultCallback,
        ActivityCompatApi23.RequestPermissionsRequestCodeValidator {

   public void startActivityFromFragment(Fragment fragment, Intent intent,
            int requestCode) {
        if (requestCode == -1) {
            super.startActivityForResult(intent, -1);
            return;
        }
        if ((requestCode&0xffff0000) != 0) {
            throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
        }
        //其实是对requestCode进行了特殊处理(位运算)
        super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
    }
        @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        mFragments.noteStateNotSaved();
      //结果回来时对requestCode进行了反向操作,看看是不是 Fragment启动的
        int index = requestCode>>16;
        if (index != 0) {
            index--;
            final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
            if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
                Log.w(TAG, "Activity result fragment index out of range: 0x"
                        + Integer.toHexString(requestCode));
                return;
            }
            final List<Fragment> activeFragments =
                    mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
            Fragment frag = activeFragments.get(index);
            if (frag == null) {
                Log.w(TAG, "Activity result no fragment exists for index: 0x"
                        + Integer.toHexString(requestCode));
            } else {
                frag.onActivityResult(requestCode&0xffff, resultCode, data);
            }
            return;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

 }

哈哈,这种做法比较取巧,但如果设置一个比较特殊的 requestCode,说不定正好能匹配上一个Fragment呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值