Android开发——LinearLayout和RelativeLayout的性能对比
来源:互联网 发布:谷歌软件下载 编辑:程序博客网 时间:2024/06/08 15:12
转自:http://blog.csdn.net/seu_calvin/article/details/53047682
0. 前言
我们都知道,新建一个Android项目SDK会为我们自动生成的avtivity_main.xml布局文件,然后它的根节点默认是RelativeLayout,在我们的理解里貌似LinearLayout的性能是要比RelativeLayout更优的,比如作为顶级View的DecorView就是个垂直方向的LinearLayout,上面是标题栏,下面是内容栏,我们常用的setContentView()方法就是给内容栏设置布局。那么LinearLayout和RelativeLayout谁的性能更高呢,好吧其实我们都知道前者性能更高,那原因是什么呢?
1. 性能对比
问题的核心在于,当RelativeLayout和LinearLayout分别作为ViewGroup表达相同布局时谁的绘制过程更快一点。
Hierarchy Viewer是随android SDK发布的工具,位于Android SDK/tools/hierarchyviewer.bat,使用它可以来检测View绘制的三大过程的耗时。如果不清楚View绘制的三大过程的,可以参考我之前写过的 Android开发——View绘制过程源码解析中详细的介绍过了,这里就不再赘述了。
通过网上的很多实验结果我们得之,两者绘制同样的界面时layout和draw的过程时间消耗相差无几,关键在于measure过程RelativeLayout比LinearLayout慢了一些。我们知道ViewGroup是没有onMeasure方法的,这个方法是交给子类自己实现的。因为不同的ViewGroup子类布局都不一样,那么onMeasure索性就全部交给他们自己实现好了。
所以我们就分别来追踪下RelativeLayout和LinearLayout的onMeasure过程来探索耗时问题的根源。本文原创,为保证错误及时更新请认准原创链接SEU_Calvin的博客。
1.1 RelativeLayout的onMeasure分析
根据源码我们发现RelativeLayout会根据2次排列的结果对子View各做一次measure。这是为什么呢?首先RelativeLayout中子View的排列方式是基于彼此的依赖关系,而这个依赖关系可能和Xml布局中View的顺序不同,在确定每个子View的位置的时候,需要先给所有的子View排序一下。又因为RelativeLayout允许ViewB在横向上依赖ViewA,ViewA在纵向上依赖B。所以需要横向纵向分别进行一次排序测量。
同时需要注意的是View.measure()方法存在以下优化:
即如果我们或者我们的子View没有要求强制刷新,而父View给子View传入的值也没有变化(也就是说子View的位置没变化),就不会做无谓的测量。RelativeLayout在onMeasure中做横向测量时,纵向的测量结果尚未完成,只好暂时使用myHeight传入子View系统。这样会导致在子View的高度和RelativeLayout的高度不相同时(设置了Margin),上述优化会失效,在View系统足够复杂时,效率问题就会很明显。
1.2 LinearLayout的onMeasure过程
源码中已经标注了一些注释,需要注意的是在每次对child测量完毕后,都会调用child.getMeasuredHeight()获取该子视图最终的高度,并将这个高度添加到mTotalLength中。但是getMeasuredHeight暂时避开了lp.weight>0的子View,因为后面会将把剩余高度按weight分配给相应的子View。因此可以得出以下结论:
(1)如果我们在LinearLayout中不使用weight属性,将只进行一次measure的过程。
(2)如果使用了weight属性,LinearLayout在第一次测量时避开设置过weight属性的子View,之后再对它们做第二次measure。由此可见,weight属性对性能是有影响的。
3. 总结论
(1)RelativeLayout慢于LinearLayout是因为它会让子View调用2次measure过程,而LinearLayout只需一次,但是有weight属性存在时,LinearLayout也需要两次measure。
(2)RelativeLayout的子View如果高度和RelativeLayout不同,会导致RelativeLayout在onMeasure()方法中做横向测量时,纵向的测量结果尚未完成,只好暂时使用自己的高度传入子View系统。而父View给子View传入的值也没有变化就不会做无谓的测量的优化会失效,解决办法就是可以使用padding代替margin以优化此问题。
(3)在不响应层级深度的情况下,使用Linearlayout而不是RelativeLayout。
结论中的第三条也解释了文章前言中的问题:DecorView的层级深度已知且固定的,上面一个标题栏,下面一个内容栏,采用RelativeLayout并不会降低层级深度,因此这种情况下使用LinearLayout效率更高。
而为开发者默认新建RelativeLayout是希望开发者能采用尽量少的View层级,很多效果是需要多层LinearLayout的嵌套,这必然不如一层的RelativeLayout性能更好。因此我们应该尽量减少布局嵌套,减少层级结构,使用比如viewStub,include等技巧。可以进行较大的布局优化。具体技巧的使用后面会继续写文总结。
- Android开发——LinearLayout和RelativeLayout的性能对比
- Android开发——LinearLayout和RelativeLayout的性能对比
- Android开发——LinearLayout和RelativeLayout的性能对比
- Android界面——LinearLayout和RelativeLayout 属性对比
- Android界面——LinearLayout和RelativeLayout 属性对比
- android入门-LinearLayout和RelativeLayout 属性对比
- LinearLayout 和 RelativeLayout的属性对比
- LinearLayout和RelativeLayout绘制过程的对比
- Android中RelativeLayout和LinearLayout性能分析
- Android中RelativeLayout和LinearLayout性能分析
- Android中RelativeLayout和LinearLayout性能分析
- Android中RelativeLayout和LinearLayout性能分析
- Android RelativeLayout和LinearLayout性能分析
- Android RelativeLayout和LinearLayout性能分析
- Android中RelativeLayout和LinearLayout性能分析
- Android中RelativeLayout和LinearLayout性能分析
- android中RelativeLayout和LinearLayout性能分析
- Android中RelativeLayout和LinearLayout性能分析
- Linux上系统日志配置文件
- 三大框架SSM——MyBatis(2)
- [Object-C]CGD&NSOperation
- struts
- 企业都应该使用开源的 POS 系统的必要性
- Android开发——LinearLayout和RelativeLayout的性能对比
- app专项测试
- BZOJ 1606 [Usaco2008 Dec]Hay For Sale 购买干草 DP---背包
- ceil和floor函数(做报表会使用到)
- css基础
- 未AC 题
- 进程池与线程池在数据仓库迁移中的多并发应用
- 关于Serverless服务的几点建议
- React Native学习路线