1、优化的原则
布局优化的思路其实很简单,就是尽量减少布局文件的层级。布局的层级少了,这就意味着Android绘制时工作量少了,那么程序的性能自然就高了。
2、具体优化方案
(1)、删除布局中无用的控件和层级
(2)、选择耗费性能较少的布局
如果布局中即可使用LinearLayout也可以使用RelativeLayout,那就采用LinearLayout。因为RelativeLayout在绘制时需要对子View分别进行了竖直和水平方向的两次测量,而Linearlayout在绘制时是根据我们设置的方向分别调用不同的测量方法。注意一点如果LinearLayout中子View使用了layout_weight属性时同样需要对子View进行两次测量以确定最终大小。LinearLayout和FrameLayout都是一种性能耗费低的布局。但是很多时候单纯通过一个LinearLayout或FrameLayout无法实现产品的效果,需要通过嵌套的方式来完成。这种情况下建议使用RelativeLayout,因为嵌套就相当于增加了布局的层级,同样会降低程序的性能。
面对复杂度高的布局(比RelativeLayout和LinearLayout多次嵌套)Constraintlayout确实更简单,绘制时间更短。但面对复杂度较低的布局,RelativeLayout比ConstraintLayout在onMesaure阶段快数倍。
总结:
性能耗费低的布局 = 功能简单 = FrameLayout、LinearLayout
性能耗费高的布局 = 功能复杂 = RelativeLayout(ConstraintLayout)
嵌套所耗费的性能 > 单个布局本身耗费的性能
(3)、提高布局的复用性(使用 <include>
布局标签)
使用 <include>
标签提取布局间的公共部分,通过提高布局的复用性从而减少测量 & 绘制时间
(4)、减少布局的层级(使用 <merge>
布局标签)
<merge>
布局标签一般和 <include>
标签一起使用从而减少布局的层级。例如当前布局是一个竖直方向的LinearLayout,这个时候如果被包含的布局也采用了竖直方向的LinearLayout,那么显然被包含的布局文件中的LinearLayout是多余的,这时通过 <merge>
布局标签就可以去掉多余的那一层LinearLayout。
(5)、减少初次测量 & 绘制时间
使用 <ViewStub>
标签
ViewStub继承了View,它非常轻量级且宽和高都为0,因此它本身不参与任何的绘制过程,避免资源的浪费,减少渲染时间,在需要的时候才加载View。因此ViewStub的意义在于按需求加载所需的布局,在实际开发中,很多布局在正常情况下不会显示,比如加载数据暂无数据,网络异常等界面,这个时候就没必要在整个界面初始化的时候将其加载进来,通过ViewStub就可以做到在使用时在加载,提高了程序初始化时的性能。
使用ViewStub需注意:当ViewStub通过setVisibility或inflate方法加载后,ViewStub就会被它内部的布局替换掉,这个时候ViewStub就不再是布局结构中的的一部分。目前ViewStub中的layout还不支持使用<merge>
标签。
尽可能少用布局属性 wrap_content
布局属性 wrap_content 会增加布局测量时计算成本,应尽可能少用
减少控件的使用(善用控件属性)
在绘制布局中,某些情况下我们可以省去部分控件的使用。
(6)、使用ConstraintLayout布局
- Constraint Layout可以在不嵌套view group的情况下实现非常庞大、复杂的布局。实现扁平化。
- Constraint Layout同时具有Relative Layout和Linear Layout的优点、特性。功能强大。
- 使用Constraint Layout来布局时性能要比其他布局方式高。
- Constraint Layout无论是通过布局管理器拖拽,鼠标控制的形式实现还是使用XML代码去写,都比较方便。