前言
在上一篇LayoutInflater 源码分析(二)中分析了LayoutInflater对include以及merge标签的处理,但是并没有找到对fragment的处理痕迹。
本文将继续探索以求揭晓答案。
可能有同学不知道,在这里提一下fragment标签的使用方式:
1 | <fragment |
这属于加载 Fragment 中的静态加载,在 XML 中写死了 class,缺乏灵活性,实际开发中并不常用,甚至已经淘汰了,所以不推荐使用。
不过这并不妨碍对它的原理探究。
分析思路
在第一篇分析中提到了 Factory 的 Hook 机制,代码如下:
1 | View view; |
为了便于理解那些个 Factory,特意大致的画了一张类图:

注意:前面代码中的mPrivateFactory 是个 FactoryMerger 对象。
可能看到这里还是会有些茫然,不过仔细一回想我们在使用 Fragment 的时候都会继承 FragmentActivity,所以去 FragmentActivity 寻找答案感觉比较靠谱。
接下去开始分析。
寻找踪迹之 FragmentActivity
查看了源码后发现,FragmentActivity 的继承结构如下

其实 Activity 就已经实现了 LayoutInflater.Factory2 接口,具体实现如下:
1 | public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { |
可以看到如果是 fragment 标签,则会交给一个叫 mFragments 的FragmentController类的对象。
但是需要注意的是:Activity 并没有调用 LayoutInflater.setFactory 使之生效,所以 Activity 并不支持 fragment 的解析。
继续看它的子类的实现。
1 | // Donut 好古老的版本啊~ |
可以看到,在BaseFragmentActivityDonut中调用了setFactory,并定义了一个dispatchFragmentsOnCreateView抽象方法,并在onCreateView里调用了它,这样就把创建 View 的工作交给了dispatchFragmentsOnCreateView。
接着,在 FragmentActivity 重写dispatchFragmentsOnCreateView,又把它交给了mFragments,咦,又回去了。
其实到这里已经可以知道,LayoutInflater把处理fragment的事情最终交给了FragmentManagerImpl。
而对于FragmentManagerImpl的分析其实已经超过了本文的界限。
但是我想再深入,看看Fragment的onCreateView方法究竟是什么时候调用的!!
所以继续跟下去:
1 | public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { |
可以看到,在处理 xml 中的属性后,会先去寻找要加载的 fragment 是否已经加载过了,如果没有则会调用fragment = Fragment.instantiate(context, fname);,这个方法也是
反射,这点其实跟 View 的处理是一样的。
接着会去调用moveToState方法,而这个方法里,我看了onCreateView方法的调用时机。
伪代码如下(太复杂,删减了绝大部分代码):
1 | // # FragmentManager |
可以看到,FragmentManager的moveToState中会去调用Fragment的performCreateView方法,而它里面,调用了onCreateView!!
onCreateView熟悉吧?就是我们使用 Fragment 第一个重写的方法!
终于找到啦!!
呼,藏得真深。
不过功夫不负有心人!~~~
爽!~
小结
FragmentActivity通过 setFactory把对fragment标签的处理委托给了 FragmentManageImpl的onCreateView方法。
最终通过反射,实例化指定的 Fragment,并调用了Fragment.performCreateView,最后到我们所熟悉的onCreateView。
整体的流程分析完毕。
另外要说的是,LayoutInflater.Factory的作用其实非常强大,我们可以 Hook 每个 View 的创建于设置,比如 AppCompact库通过AppCompactViewInflater Hook 了大部分 View,给我们提供了向下兼容的功能;
另外它也还可以配合 DayNight 实现夜间模式功能,有兴趣可以去看看AppCompactActivity、AppCompactViewInflater等类,有机会再讲吧。
到此对于 LayoutInflater 的源码分析已经结束,在查看源码的过程中发现一枚彩蛋,下一篇分享。
推荐阅读
一步一步深入理解CoordinatorLayout
ViewStub是如何实现懒加载的
Space源码分析
LayoutInflater 源码分析(一)之 inflate 深度分析
LayoutInflater源码分析(二)之include以及merge标签的处理