
Android setContentView 源码解析
Android开发的同学们对setContentView肯定都不陌生,但凡写到Activity,都离不开这个函数,今天我们就来看看它内部的实现吧!
备注:本文基于Android 8.1.0版本。
1、Activity 与 AppCompatActivity的区别
当我们在老版本Android SDK开发的时候新建的Project的默认继承的是Activity,而在5.0之后默认继承的就是AppCompatActivity。二者的区别从AppCompatActivity的注释中可窥一斑。
翻译过来就是AppCompatActivity是所有使用了Support包中 ActionBar特性的Activity的父类。
关系可以这么形容:AppCompatActivity————>FragmentActivity————>Activity。
2、setContentView
AppCompatActivity中的setContentView也非常简洁,可以看出来需要去代理类中继续查看代码。
而代理类实现的setContentView是在AppCompatDelegateImplV9中实现的:
3、createSubDecor
setContentView的第一步就是确保SubDecor被install,下面源码中有注释
3.1 requestWindowFeature
3.2 mWindow.getDecorView()
各位小伙伴应该都知道Android里的Window这个类的实现子类其实是PhoneWindow,所以我们直接取PhoneWindow中去查getDecorView这个函数。最终会走到这里,注意下面两个标注了重点的地方
generateLayout函数过多,此处不贴出代码,值只分析下过程:
设置一些Window的属性;
根据Window属性选择一个layoutResource,这些layoutResource有一个共性是都有一个@android:id/content的布局,因为在AppCompatDelegateImplV9的createSubDecor函数里会用到这个content;
选出layoutResource之后会进入一句关键的代码:mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);layoutResource就被inflate出来并且添加到DecorView中了。备注,添加View的时候使用的LayoutParams是MATCH_PARENT;
3.3 再回到createSubDecor
此时就开始创建真正的subDecor了,也有四个可选的layout,根据之前设置的属性来选择,然后去inflate出来。
3.4 mWindow.setContentView
开始设置PhoneWindow的contentView,再把代码切到PhoneWindow中
备注:到了这里,SubDecor 已经被添加到了PhoneWindow中,并且@android:id/content是SubDecor中的action_bar_activity_content。接下来别的操作是关于细节的设置。
4. 再回到setContentView
此时我们可以看出setContentView中最复杂的代码就是ensureSubDecor,接下来的代码就只是使用SubDecor中的content,将我们传入的layout inflate出来然后加进去。
5、总结
setContentView的过程就是通过PhoneWindow创建DecorView,然后创建SubDecor,最终将传递进来的布局add进来。
这样大家也更容易明白为什么通过一些性能分析工具查看布局层次及数量的时候总是比我们自己写的Layout多,也更容易明白对Activity设置View的函数被命名为setContentView。
作者:貌似许亚军
来源:简书
