Fragment 的源码实现 (完结)
Fragment 实际上 是 把 View 封装了一下, Fragment 中 onCreatedView 返回的 View 最终 会被 添加到 Fragment被添加到 FragmentMananger 的时候 对应 container 容器中. 最后一部分 为梳理的 Fragment 和 Activity 之间的关联.
下面 主要 是 根据 我们 平时 使用 Fragment 的方式 梳理一下 Fragment 对应的源码实现:
-------------------------------------------------------------------------------------------------------
1. 如果想要使用 Fragment, 首先要获取到 FragmentManangerImpl 这个对象.
第一步:
第二步: mFragments 初始化的地方为: FragmentManangerImpl 使用的为 默认构造函数.
2. 使用 Fragment 的时候 是以 事务的方式 对 修改进行提交的, 通过 beginTransaction() 来 获取到 FragmentTransaction 对象.
第一步: 实际 使用 beginTransaction() 方法 获取到 的是一个 BackStackRecord 对象,
第二步: BackStackRecord 类 是 FragmentTransaction 的子类, 且实现了 Runnable 接口
3. 如果 我们想 向 Activity中 添加一个展示的 Fragment, 则 是 通过 BackStackRecord 提供的 add 和 replace 方法 来进行添加或者删除 Fragment: 但 实际上 我们 在 一个 BackStackRecord 上执行 add 或 replace 只是 在 BackStackRecord 中对应的 Op 链条中 添加 一个 Op 对象, Op 对象 的实例变量中 保留了 操作的 类型 和 本次操作 对应的 Fragment.
第一步:
第二步:
第三步: doAddOp 的实现是 往 BackStackRecord 对应的 Op 链中 增加一个 Op 对象. fragment 的 mContainerId 和 mFragmentId 的值 为 传入的 containerViewId 这个值.
第四步: 把 上一步 封装好的 Op 对象, 添加到 BackStackRecord 对应的 Op 对象 链条中.
4. 当我们 完成 add 和 replace 的操作 之后, 我们 可以使用 BackStackRecord 中的 commit 进行 事务的提交.
第一步:
第二步: BackStackRecord 被执行 commit 之后,会把 自己 放入到 FragmentMananger 对应的队列中去.
第三步: 首先会 把 BackStackRecord 作为 Runnable 的对象 放入到 mPendingActions 这个队列中, 然后 把 mExecCommit 放入到 mActivity.mHandler 对应的 looper 中,
第四步: 其中 mExecCommit 对应的实现为:
第五步: 在 execPendingActions 中实际上是 遍历 mPendingActions 中的 所有 BackStackRecord 对象, 然后 作为 Runnable 对象 来 执行 BackStackRecord 中 对应的 run 方法:
5. 在 BackStackRecord 中 对应的 run 方法的实现为:
第一步: 如果 要被 替换的 Fragment 和 参数传入的 Fragment 相同, 则不会 调用 mMananger 的 addFragment 方法.
如果 要被 替换的Fragment 和 参数传入的 Fragment 不同, 则把 老的 Fragment 添加到 op 的 removed 这个 数组中, 然后删除 老的 Fragment , 然后 调用 mMananger 的 addFragment 把 新的 Fragment 添加 到 FragmentMananger 中.
第二步: moveToStateNow : 这个参数 决定是否 立即把 Fragment 的 mState 同步 成 FragmentMananger 对应的 state.
第三步 :把 Fragment 标记为 active 状态:
6. Fragmet 的 状态 切换:
第一步 : 在 FragmentMananger 中 调用 moveToState (Fragment f) , 这个时候实际上 是 调用 moveToState(f, mCurState [ 当前FragmentMananger 对应的状态, 0 , 0 , false).
第二步:
第三步 : . 在 switch 对应的段落中, 则 根据 Fragment 本身的 mState 来选择 switch 的入口, 然后 开始执行.
第四步: 注意 这里的 switch 是没有 break 语句的, 因此 当 根据 Fragment 的 mState 进入到 switch 的某个分支 之后, 则会继续执行:
第五步:
第六步: 如果 Fragment 的 mState 大于 FragmentMananger 中 mCurState , 则 说明 当前 Activity 在走 衰减的 周期:
第七步 : 当 FragmentMananger 的 状态 为 小于 ACTIVITY_CREATED 的时候 则 销毁 Fragment 对应的 视图 View :
第 八 步: 当 FragmentMananger 的 状态 为 小于 CREATED的时候, 则 才会 去调用 Fragment 对应的 onDestroy 方法.
9. 小总结 :
Fragment 设计的经典之处是 在 moveToState 这个地方, 这里 使用了 不带 break 的 switch 语句. switch 的 判断变量 为 Fragment 中的 mState 这个状态的值, 最终值 为 moveToState 中传入的 mNewState(这个值实际上是 FragmentMananger 的 State), 所以 不管 传进来的 Fragement 是 什么 状态, 都会被 转成 和 FragmentMananger 保持一致的状态.
10. Fragment 与 Activity 生命周期直接的关系为:
Activity 在 回调方法中 会 通过 FragmentMananger 提供的 movetToState 来修改 FragmentMananger 对应的状态 ,以便和 Activity和 FragmentManager 的状态保持一致,
---------------------------------------------------------------------------------
第一步 :. moveToState 做了两件事情,
第一件: 把 FragmentMananger 当前的状态设置为了 newState,
第二件: 遍历 mActive 中的所有 Fragment, 然后把 Fragment的状态扭转成 newState.
第二步. moveToState 被调用的位置为:
第三步:. 而 dispatchCreate 被调用的位置为:
第四步. Fragment 对应的其他状态的执行:
dispatchCreate 是在 : Activity 的 onCreate 方法中执行的.
dispatchActivityCreated 是在 : Activity 执行完 onCreate 方法之后 执行的.
dispatchStart 和 dispatchResume 方法 是在 : Activity 执行完 onStart 和 onResume 之后 执行的 ( 一 一对应).
dispatchPause (Fragment.STARTED) , dispatchStop(Fragment.STOPPED) 以及 dispatchDestroy (Fragment.INITIALIZING) 是在 : Activity 对应的回调方法之前 完成的.
图1:
图2:
图3: