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

更多相关文章

  1. 关于 android Intent 传对象和对象数组的一些操作
  2. Android(安卓)(Android(安卓)studio3.0.1)一篇可以实现app多语言的
  3. android代码中打开系统设置界面
  4. Android(安卓)selinux配置和用法
  5. 【Android2D游戏开发之四】Android(安卓)游戏框架(一个游戏角色在
  6. android intent相关
  7. 记录下android studio 重命名包名
  8. 天气预报(三)
  9. android背景图片更换——经典例子

随机推荐

  1. Android(安卓)HTTP实例 使用GET方法和POS
  2. 利用WebView通过javascript调用android j
  3. android人脸识别技术浅析
  4. Android中的布局 Layout
  5. Android基础 : Android(安卓)Service[转]
  6. Android加密
  7. 关于Android(安卓)NDK中调用第三方的动态
  8. Android(安卓)RecyclerView嵌套的滑动冲
  9. 程序时提示: No compatible targets were
  10. Android(安卓)OS 现身 HTC TyTN II