大家总是说提高绘制效率,也知道一些技巧,但是在界面出现卡顿的时候怎样去对症下药才是重点。比如:过度绘制,Google为开发者提供了很好的开发者工具,打开之后一眼就能看出,但是对于过度嵌套的问题呢?打开Hierarchy View都好麻烦,今天就测试一下几个组件的绘制情况,对优化有一个相对具体的概念,就知道该如何下手了。
一般布局
0、准备
先来看单层嵌套(即一个ViewGroup,一个TextView)
自定义ViewGroup、自定义TextView(ViewGroup分别继承LinearLayout、RelativeLayout、FrameLayout、ConstraintLayout)
1、LinearLayout
LinearLayout.pngonMeasure | onLayout | onDraw | |
---|---|---|---|
LinearLayout | 2 | 1 | 0 |
TextView | 2 | 1 | 1 |
TextView(weight=1) | 4 | 1 | 1 |
我们从表中分析三个方法的执行次数,主要是OnMeasure()方法,因为布局中的各个元素都是按照measure->layout->draw的顺序执行,为保证元素处于正确的位置、拥有正确的大小,measure方法在不同的ViewGroup中执行的次数差异是比较大的,此处我们也是着重比较这个。
2、RelativeLayout
RelativeLayout.pngonMeasure | onLayout | onDraw | |
---|---|---|---|
RelativeLayout | 2 | 1 | 0 |
TextView | 4 | 1 | 1 |
3、FrameLayout
FrameLayout.pngonMeasure | onLayout | onDraw | |
---|---|---|---|
FrameLayout | 2 | 1 | 0 |
TextView | 2 | 1 | 1 |
4、ConstraintLayout
ConstraintLayout.pngonMeasure | onLayout | onDraw | |
---|---|---|---|
ConstraintLayout | 2 | 1 | 0 |
TextView | 2 | 1 | 1 |
从对比中可以看出,除RelativeLayout之外,其实各个ViewGroup间差别不大,大家可以根据需要随意使用,但是在出现双重甚至多重嵌套的时候就要注意了。
多重嵌套
0、基本布局
基本布局.png1、Linear+Linear
onMeasure | onLayout | onDraw | |
---|---|---|---|
Linear | 2 | 1 | 0 |
Linear2 | 2 | 1 | 0 |
TextView | 2 | 1 | 1 |
TextView(weight=1) | 4 | 1 | 1 |
onMeasure | onLayout | onDraw | |
---|---|---|---|
Linear | 2 | 1 | 0 |
Linear2 | 2 | 1 | 0 |
TextView | 2 | 1 | 1 |
TextView(weight=1) | 4 | 1 | 1 |
2、Relative+Relative
Relative+Relative.pngonMeasure | onLayout | onDraw | |
---|---|---|---|
Relative | 2 | 1 | 0 |
Relative2 | 4 | 1 | 0 |
TextView | 8 | 1 | 1 |
3、Linear + Relative(外层是LinearLayout)
Linear+Relative.pngonMeasure | onLayout | onDraw | |
---|---|---|---|
Linear | 2 | 1 | 0 |
Relative | 2 | 1 | 0 |
TextView | 4 | 1 | 1 |
4、Frame + Frame
Frame+Frame.jpgonMeasure | onLayout | onDraw | |
---|---|---|---|
Frame | 2 | 1 | 0 |
Frame | 2 | 1 | 0 |
TextView | 2 | 1 | 1 |
5、Constraint + Constraint(其实这只是测试,真实情况应该避免这样使用)
Constraint+Constraint.jpgonMeasure | onLayout | onDraw | |
---|---|---|---|
Frame | 2 | 1 | 0 |
Frame | 4 | 1 | 0 |
TextView | 4 | 1 | 1 |
通过测试,大部分情况都是可以接受的,除了第二种Relative的嵌套,如果有2次甚至3次嵌套,这简直就是灾难性的。
当然,这只是得出了一个概念,具体使用的时候大家按需所用就可以,简单的界面使用LinearLayout就好,如果出现需要双重Relative的时候记得用Constraint替换就可以,当然这并不能说执行的次数少就快,因为并没有做运行时间测试,但是从侧面表现出布局选择的重要性,如果有兴趣的同学可以用Android的Hierarchy View继续测试。如果你想要极致的性能,可以自定义ViewGroup,可参考自定义ViewGroup的例子,至于这是为什么当然要从源码里面找答案了,网上这样的解读很多,我就不赘述了。
其实,看了measure()里面的measureChild()方法就大概明白了: )
网友评论