moveToState是FM中一个相当长的函数,但Fragment任何的操作add,remove …最终都会调用这个函数,从字面上可以理解,fragment要从当前状态切到newState里面干些什么都在这个函数中。
Fragment有六种State,初始状态是INITIALIZING:

static final int INITIALIZING = 0;     // Not yet created.static final int CREATED = 1;          // Created.static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.static final int STOPPED = 3;          // Fully created, not started.static final int STARTED = 4;          // Created and started, not resumed.static final int RESUMED = 5;          // Created started and resumed.int mState = INITIALIZING;

那么看看 对Fragment的各个操作分别是如何调用moveToState的。

操作 调用 说明
addFragment moveToState(fragment) 实质调用moveToState(f, mCurState, 0, 0, false);
attachFragment moveToState(fragment, mCurState, transition, transitionStyle, false);

可以看出,addFragment,attachFragment的newState都是向fm的域mCurState看齐的

mCurState的值是如何来的呢?

在fm中只有一处对mCurState进行赋值。

void moveToState(int newState, int transit, int transitStyle, boolean always) {if (mHost == null && newState != Fragment.INITIALIZING) {throw new IllegalStateException("No host");}if (!always && mCurState == newState) {return;}mCurState = newState;if (mActive != null) {boolean loadersRunning = false;for (int i=0; i<mActive.size(); i++) {Fragment f = mActive.get(i);if (f != null) {moveToState(f, newState, transit, transitStyle, false);if (f.mLoaderManager != null) {loadersRunning |= f.mLoaderManager.hasRunningLoaders();}}}if (!loadersRunning) {startPendingDeferredFragments();}if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {mHost.onSupportInvalidateOptionsMenu();mNeedMenuInvalidate = false;}}}

该函数被moveToState(int newState, boolean always)所调用,而后者又被

        mStateSaved = false;moveToState(Fragment.CREATED, false);}public void dispatchActivityCreated() {mStateSaved = false;moveToState(Fragment.ACTIVITY_CREATED, false);}public void dispatchStart() {mStateSaved = false;moveToState(Fragment.STARTED, false);}public void dispatchResume() {mStateSaved = false;moveToState(Fragment.RESUMED, false);}public void dispatchPause() {moveToState(Fragment.STARTED, false);}

那么上面这些函数又会被谁调用到呢?FragmentActivity!

FragmentActivity生命周期 fm被调用函数
onCreate dispatchCreate()
onStart() dispatchStart() 及 dispatchActivityCreated()
onStop() dispatchStop()
onPostResume() dispatchResume()

小结

fm中mCurState的值是完全随着其FragmentActivity生命周期变化而变化的,那么也就说明每当有fragment 添加进来的时候,其newState都是和其父FragmentActivity的当前生命周期是相对应的。

拆解moveToState结构

长长的函数,提炼一下

if (f.mState < newState) {switch (f.mState) {case Fragment.INITIALIZING://some codecase Fragment.CREATED:if (newState > Fragment.CREATED) {//some code}case Fragment.ACTIVITY_CREATED:case Fragment.STOPPED:if (newState > Fragment.STOPPED) {//some code}case Fragment.STARTED:if (newState > Fragment.STARTED) {//some code}}} else if (f.mState > newState) {switch (f.mState) {case Fragment.RESUMED:if (newState < Fragment.RESUMED) {//some code}case Fragment.STARTED:if (newState < Fragment.STARTED) {//some code}case Fragment.STOPPED:if (newState < Fragment.STOPPED) {//some code}case Fragment.ACTIVITY_CREATED:if (newState < Fragment.ACTIVITY_CREATED) {//some code}case Fragment.CREATED:if (newState < Fragment.CREATED) {//some code}}}f.mState = newState;

小结

在switch的每个case里是没有添加break的,也就是从fragment当前的状态开始一直执行掉剩下的所有case,所以fragment添加后,不论其父FragmentActivity处于什么状态,他都会从头执行自己的生命周期。

分析每个状态干了些啥

当fragment刚添加到父组件中时,f.mState < newState

Fragment.INITIALIZING

f.mHost = mHost;f.mParentFragment = mParent;f.mFragmentManager = mParent != null? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();f.mCalled = false;f.onAttach(mHost.getContext());

之前fragmnet是一个完全独立的对象,和父Fragment或父FragmentActivity一点关系没有,那么经过了INITIALIZING这一步,算是认祖归宗了。那么onAttach的意义也在于此。
而后在fragment.mFromLayout条件为true时会执行如下代码

if (!f.mRetaining) {f.performCreate(f.mSavedFragmentState);}f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), null, f.mSavedFragmentState);if (f.mView != null) {
/* some code */f.onViewCreated(f.mView, f.mSavedFragmentState);}

通过performCreateView间接回调onCreateView得到fragment的View,拿到该View后就会回调onViewCreated

Fragment.CREATED

而后在fragment.mFromLayout条件为false时会执行:
根据mContainerId得到View容器container,并且将fragment的onCreateView所返回的View添加到容器container中。
而后顺序调用
f.onViewCreated(f.mView, f.mSavedFragmentState)

f.performActivityCreated(f.mSavedFragmentState)

Fragment.ACTIVITY_CREATED,Fragment.STOPPED,Fragment.STARTED没有什么实质的工作,走了个过场。

小结

上面的过程基本上可以一览fragment的添加过程:
1.将fragment和父组件关联起来。
2.将fragment中的View添加到父组件的View容器中,这样就能显示出fragment的View出来了。

Fragment之底层关键操作函数moveToState相关推荐

  1. 文件操作函数在VFS层的实现

    文件操作函数在VFS层的实现 参考"Understanding Linux kernel"中的"12.6 Implementations of VFS System Ca ...

  2. C语言的常用字符串操作函数(一)

    一直做的是单片机相关的程序设计,所以程序设计上更偏向底层,对于字符串的操作也仅限于液晶屏幕上的显示等工作,想提高下字符串操作的水平,而不是笨拙的数组替换等方式,翻看帖子发现C语言的字符串操作函数竟然这 ...

  3. JavaScript中常见的字符串操作函数及用法汇总

    转载地址:http://www.jb51.net/article/65358.htm 这篇文章主要介绍了JavaScript中常见的字符串操作函数及用法,实例汇总了javascript常见的字符串转换 ...

  4. C语言 文件操作 深度解析 #重点知识:文件操作函数的使用#

    文章目录 前言 1. 为什么使用文件 2. 什么是文件 程序文件 数据文件 3. 文件的打开和关闭 4. 文件的顺序读写 `fgetc` `fputc` `fgets` `fputs` `fprint ...

  5. python中和操作目录相关的函数包括_python文件和目录操作函数小结

    <python 与数据挖掘 > 一 导读 前 言为什么要写本书?Python是什么? Python是一种带有动态语义的.解释性的.面向对象的高级编程语言.其高级内置数据结构,结合动态类型和 ...

  6. linux协议栈skb操作函数

    一. SKB_BUFF的基本概念 1. 一个完整的skb buff组成 (1) struct sk_buff--用于维护socket buffer状态和描述信息 (2) header data--独立 ...

  7. SystemV 信号量(一) —— SystemV信号量的相关操作函数(semget / semop /semctl)

    SystemV IPC 方案的相关内容都是通过 "房间密码"来创建房间,获取到房间的ID,后面其他进程也可以根据这个房间密码来拿到同一个房间的ID.这是理解下面这些操作函数的关键. ...

  8. Linux 高并发学习笔记 - Linux 目录操作函数

    1.6.4 Linux 目录操作函数 Linux 高并发学习笔记 - 笔记索引 文章目录 1.6.4 Linux 目录操作函数 前言 切换工作目录 查看工作目录 创建目录 重命名目录 移除目录 遍历目 ...

  9. [C语言]文件操作函数

    [C语言]文件操作函数 ​ 本文主要学习**fopen,fclose,fgetc,fgets,fputc,fputs,fwrite,fread,feof**这几个文件操作函数. ​ 以上函数,需要导入 ...

最新文章

  1. DllMain中不当操作导致死锁问题的分析--死锁介绍
  2. SQL取xml中节点值
  3. hdu 2222:Keywords Search
  4. boost::mp11::mp_valid相关用法的测试程序
  5. linux设备驱动归纳总结(五):4.写个简单的LED驱动
  6. python-3.6.2安装
  7. 5-1 duck typing的概念
  8. 计算机驱动安装的几个方法,显卡驱动怎么安装 三种方法教程
  9. 我的家乡html网页设计,创作一个以“我的家乡”为主题的网站
  10. TAOCP-Reading-计算机程序设计艺术阅读-1-1
  11. Egret引擎游戏内存优化指南
  12. 2020-10-13携程招聘算法题
  13. 使用xmarks同步 chrome ie firefox safari书签
  14. 群晖docker给showdoc添加ssl证书
  15. vue 父组件与子组件直接的相互传值(愚见)
  16. qq家园里游戏c语言,盘点腾讯旗下5款过气游戏,全部玩过的人都该结婚了吧
  17. 数仓即席查询---Presto
  18. 计算机网络中什么叫总衰耗_计算机网络中的四种延迟分别是什么?
  19. 【NI Multisim 14.0操作实例——最小系统电路】
  20. 5G融合行业专网解决方案分析与研究

热门文章

  1. day 01 ————立志运维的第一天开始,承若书!
  2. Yarn 问题发现与解决
  3. php 接收多图片base64
  4. openstack环境准备
  5. 《Linux From Scratch》第三部分:构建LFS系统 第八章:让LFS系统可引导 - 8.2. 创建 /etc/fstab 文件...
  6. faster rcnn结构
  7. Windows Server 2012配置***服务环境
  8. 一个 MVC 框架以 MVVM 之「魂」复活了!
  9. 网络工程原理与实践教程实验安排
  10. Oracle体系结构中的各种名称