Creating a great UI is the goal of every programmer. To do so, the first step is to understand how the system works, so that we can coordinate better, take advantage of its advantages and avoid its flaws. Have you ever wondered how your layout is genetically generated from xml files. Let’s try to learn a little bit about it today
It basically consists of 3 main steps
Step 1: Measure
Goal : Determine view size.
Size here includes the size of the child view and its dependencies with the parent view. View size is determined in two ways:
- measured width & measured height – the view will be measured in the parent view.
- width & height (also known as: drawing width & drawing height) – Actual size on the screen, at the time of drawing and after layout.
Step 2: Layout
Objective: Set position and size (drawing width & drawing height) for the view and all the child views in it.
Similar to step 1: Recursively traverse the top down view of the tree. Each parent view will locate all of its children according to the size measured in the previous step.
The positioning is done on the
onLayout(boolean changed, int left, int top, int right, int bottom) method
onLayout(boolean changed, int left, int top, int right, int bottom) where left, top, right and bottom are relative to the parent view. When overriding
onLayout() , we have to call
layout() on each child view
Step 3: Draw
After determining the size and position, the view can now draw itself. In
onDraw (Canvas) , the
Canvas object creates (or updates) a list of OpenGL-ES (displayList) commands to send to the GPU.
Altogether, it will look like this. This is an image from my old presentation slide.
That’s it, this is how each view in our xml file is drawn! But what happens when we change the view properties? when animations are animated or user input or if we decide to change them?
When things change …
When the view properties change, the view will notify the system. Depending on the changed properties, the view calls:
- Invalidate – calls
onDraw ()only for the current view
- requestLayout -> call back view root and go through the whole process (measure → layout → draw)
Here I use the phrase request layout, layout pass with the same meaning to perform the layout process.
A simple classic example of a
requests a layout scenario: Let’s say we have 2 views that are relatively close to each other in a RelativeLayout. Furthermore, if one view changes its size – it results in the other view being repositioned and possibly resizing itself. So we changed the properties of a child view, but it made the entire view outdated.
Situations like these remind us that it’s important to have effective layouts, so the layout will execute smoothly and skip frames.
No need to change the view, right after creating the view, there is already a layout pass phenomenon. So when layout pass happens more than 2 times? RelativeLayout
Always run at least 2 layout passes: First according to the requirements of each view. Then the layout will evaluate the relationship between the views, calculate the weight, height, etc. and finally perform another layout, to determine the final position to render.
Usually run a single layout, but if you use
weight it is different. That case is similar in the process mentioned above:
LinearLayout performs the first transition according to each view request. Then it is possible to calculate the size of the views by
weight and finally the second layout pass.
Often also a layout pass. However, if we use the wrong
weight or use “fill *” in the
layout_gravity property – a second layout pass error could occur.
In the simplest case, 2 times the layout pass may not affect performance much. If left unattended, however, it can be aggregated quite quickly and the process becomes a lot more expensive.
Circumstances that need attention
Deep view hierarchy – The layout process can be expensive in a way. Therefore, the deeper and more complex our view hierarchy is, the more time-consuming layouting will be. It can be said that avoiding deep view hierarchy is avoiding nested layout
Double taxation causing object is close to the root view – Remember that when request layout will request up to the rootview (like family genealogy). For views that have a double layout, each child view will automatically double the number of drawing participation. This leads to a dizzying increase in the work to be done like a flowing waterfall.
Remember that the layout process starts at the top of the hierarchy, all the way down. Normally, Grandma’s self-layout pass has already been lost 2 times. So, if Grandma asks Dad to layout 2 times and Dad asks Daughter to layout 2 times and the daughter asks Teddy to layout 2 times – overall Teddy participates in 2³ = 8 times of layout pass. Now you see the price to pay.
A lot of nested views up to 6 7 turns will happen. Although those are functions that do not take too much time and resources to execute, sometimes only 0.00000x seconds, but with the screen with hundreds of different views and view groups, what will happen when the code improves performace even a little is precious already.
Flatten the hierarchy- Flatten hierarchy
- Delete useless views
- Try to flatten the layout hierarchy.
- Custom views are efficient because they can be more precise for your application needs.
Minimize requests layout
Just request the layout if you don’t really need it.
Now we have a constraint layout that helps us solve the above problems. However, many people still do not realize its real value. The layout pass only happens once and it helps us very well with complex views. Of course, with too simple views, it is not necessary to use constraintlayout, but when you encounter difficult screens, use constraint layout, it is easier to use than you think, moreover with the increasingly popular motion layout, the Using constraint is also gradually mandatory if we want to have unique animations created by the motion layout.
Back then I did the creation of 1 image with 2 different layouts and here are the results:
You see, the effectiveness of the constraint layout is worth it for us to use more often. Although there are also a few limitations (using too many constraints together, not optimal when used with layout notification, item recycleview, …) but with complex views, nothing better than constraint layout.
This article was translated by me from a long time article on Medium but now its value is still very effective. Thank you for your interest.