原文链接:Multi-pass ViewGroup and performance
2009年Romain Guy写了关于使用RelativeLayout替代两个LinearLayout的好处的文章,不幸的是,很多人阅读那篇文章以后便假设RelativeLayout对比LinearLeyout来说,在所有的场景下会更好用。这是完全错误的假设。
那篇文章写得很好,讲解了应该减少视图层级和尽量少使用对象。当然第一原则是使视图尽量扁平化,避免不必要的容器,使用merge标签等。
然而,这个例子并没有使得RelativeLayout比LinearLayout要好。实际上如果你查看RelativeLayout的实现,你会发现它的孩子会调用onMeasure两次!这样会降低效率。如果我们有很复杂的页面结构,而RelativeLayout处于它的根节点,那将会是很大的性能开销。所以最好不要把RelativeLayout放在视图树的顶层。
当使用weight的时候,LinearLayout的子控件也会调用两次,为了计算所有控件的正确的大小。
在性能考虑上,还需要注意ListView的情况。由于多通道的计算和行控件的创建,ListView的布局如果使用wrap_content也会降低性能。
我们举个简单例子。
我们有下面这样的xml布局:
使用RelativeLayout作为父容器。我们将会观察RelativeLayout的性能。并且ListView设为wrap_content。
1 | <RelativeLayout |
然后把item的布局如下:
1 | <RelativeLayout |
我们运行一下。假设有20行,那么TextView就会调用320次onMeasure!!!
这里我们有3点可以提升的地方,减少一半的计算次数。
- 把RelativeLayout转换成LinearLayout
- 把item的wrap_content改为match_parent
- 把每一行的item容器由RelativeLayout转为LinearLayout
我们把次数降低到了40次(减少了8倍),加载时间加快了100ms,在复杂的布局上,提升会更显著。