Android Fragment 体系源码跟踪笔记(2)

  1. FragmentTransaction的commit()/commitAllowingStateLoss()调用的都是commitInternal(boolean allowStateLoss),区别就是allowStateLoss,一开始会先检查一下mCommited,如果已经commit则抛异常,否则mCommited = true, 如果mAddToBackStack,那么会请求FragmentManager为这个Transaction分配一个可以追溯的Index(mManager.allocBackStackIndex(this)),否则index=-1作为一个无效值,index会作为返回值.真正的操作则是在将该Transaction加入到FragmentManager的queue中以后的事了(mManager.enqueueAction(this, allowStateLoss);)
  2. BackStackRecord还提供了popFromBackStack(boolean doStateMove)来进行逆操作(命令模式的一个扩展),操作其实就是按照Op的cmd进行逆操作(replace时的remove数组这时候派上用场了),doStateMove会决定是否会update一下state,最后,因为BackStackRecord被弹出了,因此之前分配的Index(如果有的话)也应该归还(mManager.freeBackStackIndex(mIndex);).

  3. FragmentManager的enqueueAction(Runnable action, boolean allowStateLoss): 这就是之前所说的FragmentTransaction(BackStackRecord)被commit时提交给FragmentManager的函数,action就是BackStackRecord(实现了Runnable),因为进行的transaction会改变Fragment体系的state,而在某些情况下,state不能被修改(临时saveInstance了,http://blog.csdn.net/fyfcauc/article/details/45502983有详述),如果指定了allowStateLoss,会进行check(checkStateLoss()),之后就是真正的添加任务,考虑到多线程,会加synchronized (this),如果发现FragmentManager以及被destroy或者没有依存的Actiivty,会抛出异常. 然后就将action加入到mPendingActions(Fragment的Transaction任务列表,lazy-ctor)中,如果在加入以后,发现mPendingActions中只有一个Task,那么会将之前post到依存的Activity的hanlder上的mExecCommit(执行execPendingActions())取消,重新post一个,这基本保证了来一个task,就会post一个mExecCommit task,注意,这里虽然action是runnable,但是action却不会被post到handler上,而是存到一个队列,由mExecCommit来进行统一的execute.

  4. FragmentManager自己内部存了mActivity作为自己attach的Activity的引用,mActivity在attachActivity(FragmentActivity activity,FragmentContainer container, Fragment parent)会被赋值,而在FragmentActivity中, onCreate()的时候就会调用此函数,第二参数container在FragmentActivity是这样初始化的:

    final FragmentContainer mContainer = new FragmentContainer() { 
    @Override
    public View findViewById(int id) {
    return FragmentActivity.this.findViewById(id);
    }
    };

    findViewById()会在Create的时候被重新回调(说白了就是为FragmentManager提供了一个可以取得Actiivty的View的接口),不过mActivity除了上面的attach以外,还会在别的地方被改变.

  5. FragmentManager有两个Fragment的引用数组:

    • ArrayList mActive: 只有调用了(Package Access)makeActive(Fragment f)才会加入. 而makeActive()只在addFragment()调用,
    • ArrayList mAdded: 只要add/attachFragment就如加入.
  6. execPendingActions()(只会在主线程被调用),会check无限递归和非主线程的case(抛异常),本质就是一个while(true)循环,操作的就是之前的mPendingActions列表,要加锁,如果发现队列不存在或者已经没有task才会break,然后会将mPendingActions中的所有Runnable引用倒腾到本地的一个Runnable列表 mTmpActions中去(为了尽早释放锁,否则要添加transaction就必须等所有当前的transaction run完才行,那显然是做死),并清空mPendingActions, 同时将主handler中如果被post的新的mExecCommit Task cancel掉(不需要了,因为当前的所有action都被取出来了,这一次就足够了),将mExecutingActions设为true避免无限递归,然后挨个的将mTmpActions的Runnable run一遍并该引用置null,后面还会有一个mHavePendingDeferredStart的check,后面再细表,最后返回一个didSomething表明 这一次mainHandler有没有拿到Task去run.

你可能感兴趣的:(android)