Android布局优化【面试篇】

在之前面试中提到过布局优化的问题,刚开始还回答上来了,紧接着面试官就开始了轰炸式提问。
如果你面试的时候对于问题会答得还可以,一般情况下面试官都会往深层次吊打你。有没有看过源码啊,这个是什么,那个是怎么实现的。

布局种类

1.LinearLayout:线性布局,我们最常使用的布局之一,布局中的View水平或竖直排列。通过android:orientation设置为horizonal和vertical。
2.RelativeLayout:相对布局,我们最常用的布局之一,View默认在左上角,通过相对位置确定各个View的位置,通常用于比较复杂的界面中。
3.FrameLayout:帧布局,布局中的View以层级的方式显示,最后放的View会显示在最上层。一般用在Fragment中使用。
4.AbsoluteLayout:绝对布局,可以设置View的绝对坐标。不推荐使用,因为无法适配屏幕分辨率。
5.TabLayout:表格布局,一般用于标签页,View可以按表给形式排列。
6.ConstraintLayout:约束布局,该布局是Google在2016发布的新布局,通过创建View的四个约束来实现View的位置。该布局相对于RelativeLayout性能更好,也更容易使用。

为什么要布局优化

问题
在app使用中,我们经常会发现,界面会出现卡顿不流畅的情况,是因为当前这个界面UI处理操作超过了16ms,则会占用下一个16ms,这就导致16ms*2都显示同一帧,就是我们所说的卡顿。

那么这个16ms是怎么来的呢?

大多数的Android屏幕是以每秒60帧来刷新的(60帧是人无法感知的画面更新的一个频率,如果超过小于60帧人的大脑与感知系统就会感知到卡顿不流畅,就像翻书那样有很明显的卡顿;如果过于大于60帧界面刷新频率更高,但是成本也会增加,更加耗电,目前3月多出的几部手机有120帧和90帧的),一帧可以说成一张图片,60帧每秒就是:1000/60=16ms,就是Android每隔16ms会发出一个VSYNC信号进行一次UI渲染,如果在16ms内没有完成渲染则会出现丢帧的现象,俗称卡顿。

如何优化16ms的问题呢?

1.尽可能地少Overdraw,就是减少过度绘制,减少布局嵌套的层次,去掉重复设置的背景。
2.减少listView中getView的耗时操作,一些自定义View尽量减少invalidate调用。
3.不要在UI线程中做过多耗时操作。

布局中优化的三种方式

使用的代码就不用再看了,只针对面试中的问题。
1.include
include主要是进行重用布局,当一些布局在多个布局中都能够使用时,我们可以将其抽取出来单独放到一个布局中,在使用时通过include标签中的layout属性将布局添加进来。
2.merge
这种类型可以作为include的一种辅助拓展,主要是为了在引用布局中产生多余的嵌套布局。在使用时merge直接当作根节点布局使用。
在使用时有一些限制:①只能当作根标签使用
②merge不是ViewGroup也不是View,所以通过inflate加载布局时必须指定一个父容器,并且对merge设置的一些属性也是无效的。
3.viewStub
viewStub实际上是一种轻量级的View,只有在需要的时候才进行显示加载数据,不需要的时候不会绘制任何东西,完全不影响性能。
虽然viewStub在不使用的时候不占用任何空间,但是每个布局都必须指定layout_width和layout_height,否则运行会报错。并且在使用了viewStub中所要替代的布局中不能包含merge标签

LinearLayout与RelativeLayou

这两个布局如何使用应该就不用讨论了,咱们接下俩分析分析两者的性能。
LinearLayout
Measure:0.738ms
Layout:0.176ms
draw:7.655ms
RelativeLayout
Measure:2.280ms
Layout:0.153ms
draw:7.696ms
首先我们通过上面的数据两者在Layout和draw中基本相同,主要差距还是在Measure中。

RelativeLayout分别对其子View进行两次测量,横向纵向各一次。由于View之间的位置彼此依赖,而这个依赖关系与View的顺序并不相同,在确定每个子View的时候需要将每个子View排序。又因为RelativeLayou允许A、B两个View,横向上A依赖B,纵向上B依赖A。所以需要进行横向纵向两次测量。
如果RelativeLayout中子View于RelativeLayout的高度和RelativeLayout高度不同则会引发效率问题,当子View很复杂时这个问题会更严重,如果可以则尽量通过padding代替margin。

LinearLayout中会对所有子View进行测量,并计算totalWeight,然后判断子View的weight属性是否最大。如果没有weight属性,则不进行二次测量。

所以在不影响层级深度的情况下,优先使用LinearLayout和FrameLayout

但是在我之前面试中面试官说的是RelativeLayout性能更好,的确,Google官方也是推荐使用RelativeLayout。

//谷歌官方对相对布局的介绍
A RelativeLayout is a very powerful utility for designing a user interface because it can eliminate nested view groups and keep your layout hierarchy flat, which improves performance. If you find yourself using several nested LinearLayout groups, you may be able to replace them with a single RelativeLayout.

大概的意思就是:RelativeLayout性能更好一点,可以消除嵌套的视图组并保持布局结构的扁平化,从而提高性能。如果有多个嵌套的线性布局组,则可以使用单个的相对布局替换。

所以RelativeLayout性能会更加强大。

你可能感兴趣的:(面试,Android)