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

  1. FragmentManagerState implements Parcelable, 就是之前说的在save state时,用来保存FragmentManager本身state的容器,其内部的成员也都是各种信息的holder:
    • FragmentState[] mActive;: 保存当前Active的Fragment的state.
    • int[] mAdded: 保存已经被Add进去的Fragment的Index.
    • BackStackState[] mBackStack: Stack中的Transaction的state.
      本身很简单,只是一个信息Parceler罢了。
  2. FragmentTransaction是一个抽象类,FragmentManager的beginTransaction()返回的是FragmentTransaction的具现类: BackStackRecord. FragmentTransaction本身对应着Transaction的概念,是一次事务,是一连串的操作的集合. 使用了命令模式,BackStackRecord对应的也有自己的state holder,BackStackState(FragmentManagerState中就有这个state类的数组), 而BackStackRecord又implements了两个接口: FragmentManager.BackStackEntry + Runnable:
    • BackStackEntry: 代表着fragment back stack中的一个entry,由addToBackStack()所创造,一个entry可以通过FragmentManager的getBackStackEntryAt(int)获得,一个注意点是,不要自己维护一个entry的引用,这样会破坏这个entry的生命周期,导致其不能及时被回收.一个entry有自己的Id和Name,Id是跨Activity唯一的,而Name则是可选的,可以在addToBackStack(String)时制定, 这是一个羽量级的接口,实现它的目的也就是为了能将Transaction栈化.
    • Runnable接口的run则是真正执行Transaction操作的部分: 其主体流程是一个while循环,从一个Op链表中不断的取出Op进行执行,根据Op的cmd域来决定不同的操作:这些操作对应的也就是Transaction的那几种操作:

      • OP_ADD: 取得Op里的Fragment引用(就是被操作的Fragment),再将该Fragment的mNextAnim设置为Op的enterAnim(Fragment进入时的动画效果),然后直接将活转交给FragmentManager的addFragment(f, false)。真正干活的还是FragmentManager,这也是命令模式的一个特点,命令封装了要进行的操作的详细信息,但是具体的操作还是交由命令收到者来执行,当然了,这是比较绝对的做法
      • OP_REPLACE: Fragment的替换相对复杂一点,这里首先要判断FragmentManager的mAdded(Fragment引用数组)是不是为null(为空的话说明现在里面根本没有Fragment,自然也不可能进行replace),遍历mAdded, 取得位置i上的Fragment引用存为 old,如果old是null或者old的mContainerId和要操作的Fragmnet的mContainerId一致,那么进一步check,如果发现old引用和要操作的Fragment是同一个,那么Op的Fragmnet为设为null(这意味这不需要进行任何操作,因为要通过replace加进去的Fragmnet的已经在里面了),否则若两者不一样,那么是需要进行操作的,Op会有一个名为removed的Fragment数组,会将old加入到这个remove数组中,并且会把old的mNextAnim设置为Op的exitAnim(Fragment离开时的动画效果),调用FragmentManager的removeFragment将old清除,还会将Transaction自己的mTransition和mTransitionStyle传入作为动画效果,遍历mAdded的循环做的其实就是遍历当前被Added的Fragment,找到所有被指定replace的Fragment,将其remove,全部remove完了以后,作为replacer的Fragment会被加入(还是调用了FragmentManager的addFragment,这里还会判断replacer是不是null,如果是null,就不需要加了,replacer为null的replace,可以理解为一个remove)
      • OP_REMOVE: 大致同OP_ADD
      • OP_HIDE: 大致同OP_ADD
      • OP_SHOW: 大致同OP_ADD
      • OP_DETACH: 大致同OP_ADD
      • OP_ATTACH: 大致同OP_ADD

      在上面这些操作以后,Manager会执行一个moveToState()的操作(后面继续分析,本质是更新Fragment体系的state),
      还会有一个mAddToBackStack的check(mManager.addBackStackState(this);),这是为了做 栈式回退操作。
  3. BackStackState存储的主要信息有:
    • int[] mOps: 不是简单的和Op的Id一一对应,相反因为Op的重要信息都可以存为int,因此mOps可以把Op的 cmd/对应Fragment的Index/enterAnim等信息都存下来,其实就是存储了Op所有的信息,这是为了序列化和本地存储.
    • int mTransition, mTransitionStyle:直接存的是 BackStackRecord的相应信息.
    • String mName:直接存的是 BackStackRecord的相应信息.
    • int mIndex:直接存的是 BackStackRecord的相应信息.
  4. 从BackStackState中恢复出一个BackStackRecord(反序列化)用的是BackStackRecord instantiate(FragmentManagerImpl fm),fm的引入是为了获取Record中的Op对应的Fragment引用,这个只有在fm的mActive中才能得到.
  5. BackStackRecord的构造强制要求一个FragmentManager(可以理解).
  6. FragmentTransaction接口的各种add/replace/remove/…方法其实就是向BackStackRecord的Op数组中不断的增加新的Op,这些操作的输入参数(Fragment引用,containerViewId)都会被进一步封装在Op对象中投递进数组,setCustomAnimations(int enter, int exit, int popEnter, int popExit)设置的参数最后会成为BackStackRecord的mEnterAnim/mExitAnim/mPopEnterAnim/mPopExitAnim. addToBackStack(String name)其实就是将mAddToBackStack设为true(真正run的最后执行时会check),同时将Name存为此Transaction的Name.注意这里还有一个mAllowAddToBackStack可以阻止AddBackStack(抛异常,可以通过Transaction的setter设置).
  7. 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);)
  8. BackStackRecord还提供了popFromBackStack(boolean doStateMove)来进行逆操作(命令模式的一个扩展),操作其实就是按照Op的cmd进行逆操作(replace时的remove数组这时候派上用场了),doStateMove会决定是否会update一下state,最后,因为BackStackRecord被弹出了,因此之前分配的Index(如果有的话)也应该归还(mManager.freeBackStackIndex(mIndex);).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值