Fragment_学习2

fragment操作流程

我们来看一下Fragment初始化的具体流程。拿add()举例:

FragmentManager:
 @Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }
首先取得FragmentTranscation类型的BackStackRecord对象。


BackStackRecord:
在FragmentTranscaction调用add()之后会生成一个新的Op类来保存用户的操作。
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        fragment.mFragmentManager = mManager;
        ...
        Op op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
    }

void addOp(Op op) {
        if (mHead == null) {
            mHead = mTail = op;
        } else {
            op.prev = mTail;
            mTail.next = op;
            mTail = op;
        }
        op.enterAnim = mEnterAnim;
        op.exitAnim = mExitAnim;
        op.popEnterAnim = mPopEnterAnim;
        op.popExitAnim = mPopExitAnim;
        mNumOp++;
    }

之后会用BackStackRecord中的两个Op类(mHead,mTail)以链表的形式来保存用户的操作。
mHead,会在加入的时候遍历。
mTail,会在back退出的时候遍历。

最后来看看commit()是怎么实现的
首先如果设置为saveStack,那么会把当前的BackStackRecord对象add到FragmentManager的mBackStackIndices(Arraylist)中,并返回list.size(),来作为Id.
 int commitInternal(boolean allowStateLoss) {
        ...
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

FragmentManager会把这个BackStack对象加入到的Handle队列中执行。mPendingActions中保存了待处理的Runnable。可以用executePendingTransactions()来立刻遍历执行mPendingActions中的run.
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mActivity.mHandler.removeCallbacks(mExecCommit);
mActivity.mHandler.post(mExecCommit);
}

在run中,会根据用户操作状态(cmd)遍历mHead链表来执行对应FragmentManager中的方法,这里比较特殊的是replace();最后把BackStack对象存入Manager中的mBackStack集合中
 public void run() {
        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);

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

        bumpBackStackNesting(1);

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

            op = op.next;
        }

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

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

这里的 mAdded是Manager中的一个List,用来保存add进来的fragment对象。这里做了一个简单的比较,如果新的fragment与List中的fragment是同一个对象,那么直接跳过,什么都不做。
如果不是同一个对象,那就把List中的fragment删掉。按照这样的写法,最后一个GruopView中,只会剩下最新替换的Fragment。
可我通过实验发现,如果把多个fragment加入到同一个GruopVIew中,然后做replace(),那么会出现只替换了最后一个fragment,第一个消失,而且他保留的情况。这里我还要再看看,果如有明白的朋友可以告诉我是怎么回事。

FragmentManager:
把新的Fragment添加到总集合(ArrayList<Fragment> mAdded) 和活跃集合(ArrayList<Fragment> mActive)中,之后具体的操作都在moveToState中执行。
public void addFragment(Fragment fragment, boolean moveToStateNow) {
        if (mAdded == null) {
            mAdded = new ArrayList<Fragment>();
        }
       ...
        makeActive(fragment);
        if (!fragment.mDetached) {
            ...

            mAdded.add(fragment);
            if (moveToStateNow) {
                moveToState(fragment);
            }
        }
    }
   

moveToState学习,请看学习3

你可能感兴趣的:(Fragment_学习2)