Fragment 原理

创建一个Fragment的流程

//创建Fragment
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.sync_viewpager_container, new Sync_SubjectExerciseFragment(),"subject");
fragmentTransaction.commit();
首先第一步就是获取FragmentManager 对象
  • AppCompatActivity 继承 FragmentActivity
  • FragmentActivity 包含 FragmentController
  • FragmentController 是一个代理
  • FragmentHostCallback 被FragmentController持有,有一个FragmentManagerImpl,真正的进行fragment操作
  • FragmentContainer view容器
FragmentTransaction
  • Fragment操作的事务,每个FragmentTransaction对象,代表着系列Fragment操作的事务
  • 操作Fragment的添加,删除,隐藏,显示时,都要使用FragmentTransaction
  • FragmentTransaction其实是个抽象类,真正的实现类是BackStackRecord
BackStackRecord
  • BackStackRecord实现了FragmentTransaction,每一个BackStackRecord对象,都代表了一次Fragment操作事务,

OP

  • op对象主要保存了FragmentTransaction操作事务中的单次操作,是相对于Fragment而言的,每个op对象,保存了add -> new Op

  • 把Fragment和操作的命令 OP_ADD映射关系

  • 最终添加到OP 列表中

  • addOp 包含了 Fragment动画

Commit(在BackStackRecord的方法)
  • 在主线程中已不执行,其实也是Handler抛出任务,等待主线程调度执行,
  • commit需要宿主activity保存状态之前调用,否则报错
  • 这是因为如果activity出现异常需要恢复状态,在保存状态之后的commit将会丢失,这和调用的初衷不符,所以会报错。
commitAllowingStateLoss
  • 也是异步执行的,但是他的不同之处在于,允许在activity保存状态之后调用,也就是说他遇到状态丢失不会报错
commitInternal (allowStateLoss)
  • 是否加入回退栈
  • 异步任务入队 mManager.enqueueAction(this,allowStateLoss)
enqueueAction
  • mPendingActions.add(action) 讲commit处理操作放置到mPendingActions列表中(ArrayList)
  • scheduleCommit 发送任务
scheduleCommit
  • mHost.getHandler().post(mExecCommit);
  • mHost 就是 FragmentActivity 的mHost 获取了主线程的handler对象,新建runnable对象,最终执行 execPendingActions()
execPendingActions
  • 将mPendingActions列表的action拷贝到mTempActions数组里
  • mTempRecords, 前者用来临时存储所有待执行的动作(mPendingActions)生成的BackStackRecord.
  • mTmpIsPop用来存储BackStackRecord是否出栈
  • removeRedundantOperationsAndExecute()这里是入口执行 BackStackRecord 真正的去执行Fragment 操作
commitNow 立即执行
  • disallowAddToBackStack() 不允许添加到回退栈中
  • mMananger.execSingleAction 立即执行
  • removeRedundantOperationsAndExecute()这里是入口执行 BackStackRecord
commitNow 为什么不允许添加到回退栈?
  • 因为以时间添加到回退栈

execPendingActions

真正的去执行Fragment 操作

  • mAdded 代表存活的Fragment
  • mTmpRecords 用于优化执行的临时变量
  • mTmpIsPop 用于优化执行的临时变量 用来存储是否出栈

removeRedundantOperationsAndExecute()

  • executeOpsTogether 这里将Ops过滤一遍
  • expandReplaceOps 方法吧replace替换(目标fragment已经被add)成相应的remove和add操作
  • executeOps () 真正处理的入口
  • moveToState 最后一个事务时需要moveTostate为true
  • record.executePopOps 对出栈事务的所有Op进行逆操作(执行出栈)
  • record.executeOps 执行非出栈事务的所有Op操作(执行commit)

executeOps 很多对fragment的操作
比如addFragment 操作

  • 是执行FragmentManager 的 addFragment
  • makeActive 更新没Active列表
  • 更新mAdded列表
  • 更新当前fragment状态
  • 最终调用moveToState

moveToState

  • 类正向的切换顺序,INITIALZEING -> CREATE -> ACTIVITY_CREATE -> STARTED -> RESUME 值变得越来愈大。代表着fragment从初始化到可见交互的状态

  • 类是反向的切换顺序,与之相反,值越来越小,代表着fragment从可见可交互到与activity分离的状态

Fragment

fragment = View + 固有属性 + state

  • view就是添加到界面中的视图,
  • 固有属性就是attr,指的是fragment的一些固有属性,不会随着fragment的生命周期发生变化
  • state,就是fragment当前的状态,fragment在生命周期变迁中会发生改变的状态,其实就是说白了,fragment就是一个拥有生命周期的自定义View

fragment状态并不等同于他的生命周期

状态

状态意义入口方法
0INITIALIZINGfragment尚未初始化或者已经被销毁dispatchDestroy
1CREATEFragement已经被创建dispatchDestroyView
2ACTIVITY_CREATEfragment所在activity已经创建成功dispatchActivityCreate
3STARTEDfragment已经可见,但是还不可以接受点击事件dispatchPause
4RESUMEfragment已经被创建,但是尚未不可见dispatchResume

Fragment 如何 添加到 Activity的?

fragment 和 activity 的生命对应的关系

moveToState (CREATE)

  • Activity#onCreate -> Fragment#onAttch -> Fragment#onCreate -> Fragment#onCreateView -> Fragment#onViewCreate -> Fragment#onActivityCreate

moveToState (ACTIVITY_CREATE)

  • Activity#onStart
    moveToState (STARTED)
  • Fragment#onCreateView -> Fragment#onViewCreate -> Fragment#onActivityCreate -> Activity#onResume

moveToState (RESUME)

  • Fragment#onStart -> Fragment#onResume -> Fragment 可见可交互
    moveToState (STARTED)
  • Fragment#onPause -> Activity#onPause -> Fragment#onStop-> Activity#onStop

moveToState (CREATE)

  • Fragment#onDestroyView -> Fragment#onDestroy

moveToState (INIT)

  • Fragment#onDetach -> Activity#onDestroy

allocBackStackIndex() 用于给加入到返回栈的BackStackRecord分配下标

  • mBackStackIndices(ArrayList) 记录 BackStackRecord
  • mAvalBackStackIndices (SparseList) 记录 mBackStackIndices 下标index(已经被回收BackStackRecord),下次mBackStackIndices存储时,直接复用

类图 -> 类的组合

时序图-> 类的交互

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值