Optimizing Layout Hierarchies
This lesson teaches you to
You should also read
It is a common misconception that using the basic layout structures leads to the most efficient layouts. However, each widget and layout you add to your application requires initialization, layout, and drawing. For example, using nested instances of LinearLayout
can lead to an excessively deep view hierarchy. Furthermore, nesting several instances of LinearLayout
that use the layout_weight
parameter can be especially expensive as each child needs to be measured twice. This is particularly important when the layout is inflated repeatedly, such as when used in a ListView
or GridView
.
嵌套使用基本的layout会产生一个很深的layout继承结构。比如嵌套的linearlayout,由其在其中使用layout_weight时,会产生两次measure。
In this lesson you'll learn to use Hierarchy Viewer and Layoutopt to examine and optimize your layout.
Inspect Your Layout
The Android SDK tools include a tool called Hierarchy Viewer that allows you to analyze your layout while your application is running. Using this tool helps you discover bottlenecks in the layout performance.
Hierarchy Viewer 可以发现有性能瓶颈的view或layout。
Hierarchy Viewer works by allowing you to select running processes on a connected device or emulator, then display the layout tree. The traffic lights on each block represent its Measure, Layout and Draw performance, helping you identify potential issues.
For example, figure 1 shows a layout that's used as an item in a ListView
. This layout shows a small bitmap image on the left and two stacked items of text on the right. It is especially important that layouts that will be inflated multiple times—such as this one—are optimized as the performance benefits will be multiplied.
The hierarchyviewer
tool is available in <sdk>/tools/
. When opened, the Hierarchy Viewer shows a list of available devices and its running components. Click Load View Hierarchy to view the layout hierarchy of the selected component. For example, figure 2 shows the layout for the list item illustrated by figure 1.
In figure 2, you can see there is a 3-level hierarchy with some problems laying out the text items. Clicking on the items shows the time taken for each stage of the process (figure 3). It becomes clear which items are taking the longest to measure, layout, and render, and where you should spend time optimizing.
The timings for rendering a complete list item using this layout are:
- Measure: 0.977ms
- Layout: 0.167ms
- Draw: 2.717ms
Revise Your Layout 改善上例中的layout
Because the layout performance above slows down due to a nested LinearLayout
, the performance might improve by flattening the layout—make the layout shallow and wide, rather than narrow and deep. A RelativeLayout
as the root node allows for such layouts. So, when this design is converted to use RelativeLayout
, you can see that the layout becomes a 2-level hierarchy. Inspection of the new layout looks like this:
上例中使用了多层嵌套的linearlayout,其实没有必要,可以用一个RelativeLayout对其优化。
在实战中尽量让布局层次扁平,不要有过深的层次。
改善后的时间:
Now rendering a list item takes:
- Measure: 0.598ms
- Layout: 0.110ms
- Draw: 2.146ms
Might seem like a small improvement, but this time is multiplied several times because this layout is used for every item in a list.
Most of this time difference is due to the use of layout_weight
in the LinearLayout
design, which can slow down the speed of measurement. It is just one example of how each layout has appropriate uses and you should carefully consider whether using layout weight is necessary.
除非 layout_weight 必要,否则少用它,它会产生重复的measure,导致性能变差。
Use Lint
It is always good practice to run the lint tool on your layout files to search for possible view hierarchy optimizations. Lint has replaced the Layoutopt tool and has much greater functionality. Some examples of lint rules are:
可以用lint对布局xml进行扫描,会发现有性能问题的部分,下面是lint扫描时遵守的几条规则:
- Use compound drawables - A
LinearLayout
which contains anImageView
and aTextView
can be more efficiently handled as a compound drawable.如果一个linearlayout中只有一个ImageView和TextView,可以用TextView的compound 简化。
- Merge root frame - If a
FrameLayout
is the root of a layout and does not provide background or padding etc, it can be replaced with a merge tag which is slightly more efficient.布局文件的根节点是<FrameLayout>时,并且没在其内定义背景,间距等,可以用<merge>代替它。
- Useless leaf - A layout that has no children or no background can often be removed (since it is invisible) for a flatter and more efficient layout hierarchy.
没有子布局并没有设置背景的可以删除掉。
- Useless parent - A layout with children that has no siblings, is not a
ScrollView
or a root layout, and does not have a background, can be removed and have its children moved directly into the parent for a flatter and more efficient layout hierarchy.一个布局没有兄弟,不是ScrollView,不是根layout,没有背景,就可以直接把它的孩子移到上层布局上,然后删除它。
- Deep layouts - Layouts with too much nesting are bad for performance. Consider using flatter layouts such as
RelativeLayout
orGridLayout
to improve performance. The default maximum depth is 10.嵌套过深的布局会产生性能问题,用RelativeLayout或GridLayout替代它。默认最大深度为10。
Another benefit of Lint is that it is integrated into Android Studio. Lint automatically runs whenever you compile your program. With Android Studio, you can also run lint inspections for a specific build variant, or for all build variants.
You can also manage inspection profiles and configure inspections within Android Studio with the File>Settings>Project Settings option. The Inspection Configuration page appears with the supported inspections.
Lint has the ability to automatically fix some issues, provide suggestions for others and jump directly to the offending code for review.