Layout Once, Layout Twice — Sold!
Pervious post discussed the way Android measure and layout views, before drawing them to the screen. So we know by now that the layout process isn’t cheap.
Moreover, there are cases in which it is done more than once, and then the process becomes even more expensive.
When might a second layout pass occur?
Always runs at least 2 layout passes: First according to each view requests. Then the layout evaluates the relations between views, calculates weights etc.. and finally performs another pass, to determine the final positions for rendering.
Generally issues a single layout pass, unless using weights. That case is somewhat similar in process to the above mentioned: LinearLayout performs a first pass according to each view requests. Only then it can calculate the view sizes according to weights distribution, and finally issues a second layout pass.
Also generally issues one layout pass. However, if we use weights wrong, or use “fill*” in layout_gravity attribute — a second layout pass might occur.
In the simple case, the two layout passes might not affect performance that much. However, without paying attention it can aggregate quite quickly and the process becomes a lot more expensive.
Situations to pay attention to
Deep view hierarchy — the layout process might be expensive on anyhow, so the deep and complex our view hierarchy is, the more time consuming the layout traversal is.
Double taxation causing object is close to the root view — remember that when requesting a layout, the request bubbles up the view tree. For a view that issues double layout, each child will automatically double the times participating in traversal. This can cascade quite quickly.
If there are many of them like in list — which copies the layout.
Nested double layout causing objects. To emphasize that this can be dangerous:
Remember that the layout pass begins on top of the hierarchy, all the way down. So if grandma asks father to layout twice, and father asks daughter to layout twice, and daughter asks teddy to layout twice — then overall teddy participated in 2³ = 8 layout passes. Expensive it might be.
So what can we do?
Use the objects in situations described above with attention.
Remove useless views
Use <merge> when including a layout
Flatter layout hierarchy will usually be beneficial.
Create custom view that will be more efficient, as can be more accurate for your application needs.
Just don’t request layout if you don’t really need to.
Another thing that can helps is:
A cool tool that helps us visualize and better understand the complexity of our layouts.
What does it do for us?
Displays complete view hierarchy
Measure time for view rendering phases
Show the view objects fields and properties
Found on Android Studio : Tools→ Android → Android Device Monitor → Hierarchy Viewer
What do we have here?
Choose your activity on the Windows panel (on left hand side)
Tree Overview shows the entire view hierarchy (on right hand side)
Tree View window (on center) displays the part of the view hierarchy selected inside the square within the Tree Overview.
Clicking a view on Tree View previews it on top of clicked box, as well as on Layout View panel (bottom right). It also show more View object properties on View Properties panel.
Select a view box, then click Layout Times icon:
then each child view box gets 3 colored dots on it:
What’s with the dots?
Each view box has 3 dots, which represents: measure, layout and draw respectively.
The dots color represents the time the system spent on the relevant phase, relative to other views in the tree.
Green — the view is in the faster 50% views on the tree
Yellow — in the slower 50%
Red — the slowest view in the tree.
Remember that these are relative to other views on the tree. So red or yellow dots don’t necessarily mean there’s something wrong with the view. View groups and complex views, for example, will naturally render slower than simple views.
We may use the Invalidate and Request Layout icons on the top bar, for debugging, and examine how they affect the layout times.
We understood better the reasons and implications of double layout pass, and have some ideas on how to improve and profile our application layout.
Next post will introduce a brand new tool to help us, among other things, improve layout performance issues mentioned before.