So let’s talk about the general flow of setContentView

When we call setContentView(int resId), we first initialize a DecorView in the window. The DecorView inherits FrameLayout and itself adds the DecorView to the window. Inflater.from(mContext).inflate(resId, contentParent) when we call setContentView(int resId), the file corresponding to the layout ID is inflatered.from (mContext).inflate(resId, contentParent), Add to this DecorView. However, LayoutInflater creates views by reading the file using XmlResourceParser, recursively iterating through it, reflecting the corresponding View, and setting it into the DecorView.

A few more words about rendering mechanics

Most phones refresh at 60hz (some phones are already 90hz(huawei p40, vivo x50) or 120hz (vivo x50 pro+, one plus 8T)). CPU and GPU. The CPU computes the UI components into Polygons, textures, and hands them over to the GPU for rasterization. For example, when a picture is displayed, it needs to be loaded into memory after calculation by the CPU, and then transferred to the GPU for rendering. The text display is complicated. It needs to be converted into texture by CPU, and then rendered by GPU. When the CPU draws a single character, the content rendered by GPU is re-referenced. Animation is a more complex process.

The measures we take

Using the merge

Merge reduces the number of layers. When we customize the View composition, we generally go directly view.inflate (context, R.layout.layout_tool_view, this); For example, if our custom view is a LinearLayout, but the root layout of the inflate is also a LinearLayout, we can replace the root layout in the XML with a merge to reduce one layer

Using the include

When reusing a layout, we can use include and merge to reduce one layer

Using a ViewStub

The ViewStub is a View that is 0 in width and 0 in height, which is invisible by default and lazy-loading is achieved only by calling the setVisibility or the Inflate function to load the target layout. The layout to be loaded is set by the Android: Layout property, commonly known as lazy loading View, which acts as a placeholder and can be understood as a very lightweight View

Use RelativeLayout and LinearLayout wisely

We’re going to use a LinearLayout when we can use both a RelativeLayout and a LinearLayout, because the RelativeLayout measures the subview twice, The LinearLayout only needs to be measured once. If measureWithLargestChild is set, the subView will measure twice.

ConstraintLayout

ConstraintLayout is expected to be used for any complex layout. Performance is greatly improved. The overhead is much lower. This class uses its own constraint resolution system to resolve the relationships between views in a completely different way from the standard layout.

Try to specify the width and height of the View, or match_parent

Because WRAP_content increases the measurement overhead

Remove unnecessary backgrounds

By default, the layout has no background, which means that the layout itself doesn’t render anything directly. However, when a layout has a background, it can lead to overdrawing. When the child View completely overwrites the parent View’s background, you can remove the parent’s background. When we set the window

Reduce transparency

Rendering transparent pixels on the screen, known as transparent rendering, is an important factor in overdrawing. Unlike normal overdraw, where the system draws opaque pixels on top of existing pixels that have been drawn to completely mask them, transparent objects need to draw existing pixels first in order to achieve the correct blending effect. Visual effects such as transparent animations, fade-outs, and shadows all involve some kind of transparency and can lead to serious overdrawing. You can improve overdrawing in these cases by reducing the number of transparent objects to render. For example, to get gray text, you can draw black text in a TextView and set a translucent opacity value for it. However, you can get the same effect by simply drawing text in gray, and with a huge performance boost.

Custom views can use ClipRect

Clipping the rectangle with Canvas. ClipRect () to avoid duplicate drawing

invalidate(Rect dirty)Invalid and useless

Other external optimizations

AsynclayoutInflater Asynchronously loads views

There are limitations to placing time-consuming layout rendering operations in child threads and then calling back to the main thread after the inflate operation has completed

  • With asynchronous constructors, the generateLayoutParams function that requires the parent of this layout is thread-safe;
  • All views built must not create handlers or call looper.mylooper; (Because it is loaded in an asynchronous thread, the asynchronous thread does not call looper.prepare by default);
  • Asynchronously converted views are not added to the parent View. AsyncLayoutInflater calls layOutinflater.inflate (int, ViewGroup, false). So if we need to add it to the Parent View, we need to add it manually;
  • AsyncLayoutInflater does not support LayoutInflater.Factory or LayoutInflater.Factory2.
  • Loading a layout with fragments is not supported.
  • If the AsyncLayoutInflater fails, it automatically falls back to the UI thread to load the layout;

X2C

Use APT technology to complete the operation of the whole process during compilation, which is equivalent to direct new View, equivalent to converting XML into View during compilation, but also has its own limitations. Not recommended for use

Jetpack Compose

Google’s Compose is designed to dispense with XML and build a simple interface component using declarative functions. You don’t need to modify any XML layout or create interface widgets directly. Instead, you just call the Jetpack Compose function to declare the elements you want, and the Compose compiler does all the rest

Use the Layout Inspector to view the hierarchy

GPU rendering speed and over drawing

Systrace

Android Studio Profiler