In the process of learning, good at summing up can quickly improve personal level, especially as a programmer. Project optimization is also a very important part, recently I thought of writing an article summary, whether it is useful for future development or to improve their own level. Before writing this article, I will make a summary based on my project experience and several online blogs. In particular, I will attach relevant links at the end of the article, although sometimes it is not necessary to know the principle. UI optimization can not be seen once, mainly at the beginning of the initiative to cultivate such a habit, the order of this article is mainly in accordance with the importance of UI optimization.

Excessive drawing

I’m sure you’ve all seen this before, but just to give you a quick overview, I’m going to focus on how we can avoid this in actual development. Overdraw is when a pixel on a screen is drawn more than once in the same frame.

1. Nested layout due to the complexity of the layout 2

Nested layout
  • Use the Merge tag
  • Use RelativeLayout and ConstraintLayout (enhanced RelativeLayout)
  • Custom Viewgroup, rewrite the Layout method
Multilayer background

I’ll break it down into roughly three cases:

  • For a single view, if you have a foreground image or color, do not set the background. This is mostly the case in imageView
  • For viewGroups, only the background color of the bottom view is set unless it is particularly needed
  • All activities have a default background and a default theme color, which is the root of the black and white screen that appears on a cold launch. If you are using the type of Activity launcher, you can set a drawable or XML for an image or color (it is recommended not to do this because XML parsing takes time). And the background of the launcher type Activity should be used to remove the memory footprint. The launcher class:
<style name="AppTheme.Launcher">
    <item name="android:windowBackground">@drawable/launch_screens</item>
</style>
Copy the code

Or (not recommended) :

<style name="SplashTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowDisablePreview">true</item>
</style>
Copy the code

After the Settings are loaded, the oncreat() method is set as follows to remove the memory footprint

@override protected void onCreate(@nullable Bundle savedInstanceState) {// Set the window background to null getWindow().setBackgroundDrawable(null); super.onCreate(savedInstanceState); }Copy the code

If it is a normal Activity, you can:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().setBackgroundDrawable(null);
    }
Copy the code

Reference link: juejin.cn/post/684490…

## Performance comparison of common layouts

To sum up a few points:

  • Same hierarchy effect, priority FrameLayout>=LinearLayout>RelativeLayout>ConstraintLayout
  • For the responsible UI, hierarchical nesting is optimized first, and ConstraintLayout and RelativeLayout are preferred
  • Careful use of the Weight and measureWithLargestChild attributes on a LinearLayout will cause 2 renderings
  • Minimize the number of invalid dependencies in ConstraintLayout and RelativeLayout to reduce the flushing of unnecessary controls

Custom view optimization

(There are still things to summarize)

onDraw

Custom View inside the most important, but also the most important part of optimization.

  • If invalidate() is required, ondraw() will always call ondraw(), which will cause memory to be created and retracted, causing memory jitter.

  • Do not frequently set invisible methods to be called, try to set the XML to the default state, reduce ondraw method calls.

  • Try not to trigger the invalidate method until the View’s contents change

  • Try to use methods such as ClipRect to improve the performance of drawing (do not draw overlapping parts).

  • Reduce drawing of unnecessary elements

  • Use Canvas.quickReject to eliminate off-screen elements as much as possible

onLayout

Any time you call requestLayout() on a View, you need to traverse the entire View tree to determine the size of each View. If there is any conflict during the measure process, it may be traversed multiple times. If the UI designer makes the effect too complex, the onLayout method needs to be customized and can reduce nesting problems and optimize the measure process.

clipRect()

This method is used to crop the canvas, and when the clipRect() method is called, only the clipped region is displayed, and the rest of the region is not. INTERSECT method has a final parameter, region. Op, which indicates the type of operation between regions and the previous Region. If this parameter is not present, default Region.

  • DIFFERENCE is the part that is different from the second time
  • REPLACE is the second one
  • REVERSE_DIFFERENCE is the second partial display that differs from the first
  • INTERSECT display
  • UNION all display
  • An XOR complement is a complete set minus the intersection fertility part of the display
  • The clipxx method only works on drawxx after the drawxx is set, not on drawn graphs.

Special label

include

Include tags are often used to extract common parts of a layout, such as all the actionbars on a page, so that they can be included directly. Matters needing attention:

  • The width and height of the outer layer can be set. The outer layer is better than the inner layer
  • You can set an ID for the outer layer. The outer ID has a higher priority than the inner ID
  • If two includes with the same ID are referenced in a layout, the first is valid and the second is invalid, but both are displayed.
The merge:

The merge tag is used as a supplementary extension to the include tag to prevent unnecessary nesting of layout files when referencing layout files. Android rendering takes time, and the more complex the layout, the worse the performance. The include tag introduced in the previous LinearLayout adds one more layer to the interface. Matters needing attention:

  • The merge must be placed at the root of the layout file.
  • Merge is not a ViewGroup. It is not a View. It declares views that are waiting to be added.
  • The merge tag is added to the A container, so all views of the merge are added to the A container.
  • Because the merge tag is not a View, the second argument must specify a parent container when rendered by the layoutconstructor.inflate method, and the third argument must be true, which specifies a parent node for the View under the merge.
  • If the Activity layout file root node is FrameLayout, you can replace it with the merge tag. This reduces the FrameLayout node by one layer after executing setContentView.
  • If the custom View inherits the LinearLayout, it is recommended to merge the layout file root node of the custom View, so that there is one less layer of nodes.
  • Because merge is not a View, all properties set on the Merge tag are invalid.
  • If the LinearLayout is referenced to the outer layer, the merge internal direction follows the direction set by the LinearLayout
ViewStub:

The ViewStub directly inherits from the View and is invisible by default without a measure process. It is only visible when the View stub is inflate once, and an exception is reported when the View is inflate again, or when it is set to Visibility. The biggest feature is use only load. Here is a brief description of a common usage scenario, sometimes there is no data on the page, there will be no data page or network abnormal page, this situation is a good use of load before use.

Matters needing attention:

  • A ViewStub can only be synchronized once, after which the ViewStub object will be empty
  • ViewStub can only be used to Inflate a layout file, not a concrete View (you can Inflate the View into a layout file)
  • Android: ID — The ID of the ViewStub itself, whether or not it is inflate, can be retrieved by findViewById to the corresponding ViewStub control itself.
  • Android :inflatedId — ViewStub is the ID of the root node in the layout that you use. After the inflate, you can retrieve the mapped layout object using findViewById
  • After viewstub.inflate (), if you want to show or hide the layout as normal, do not inflate() again.
  • When a ViewStub node is defined in XML, it cannot contain other nodes internally. That is, the ViewStub is a self-closing node. If a layout view is to be displayed through the ViewStub, it must be defined in a separate XML file.
Comparison of ViewStub to Gone

A View set to GONE does not take up layout space, but does class initialization; If the ImageView sets SRC to a BitmapDrawable, the image will be loaded inside the ViewStub and will only be loaded after the inflate is created in the code, without consuming memory.

The performance comparison: blog.csdn.net/wolinxuebin…

space

Space is often used for gaps between components, and draw() is empty, reducing the process of drawing and rendering. Spacing between components using Space improves drawing efficiency, especially for dynamic spacing. Since draw() is empty and no task rendering is done to the view, it is not possible to set the background color for Space, and it is obviously inappropriate to set the color for the desired interval. Space has the advantage of setting spacing relative to View without using DRAW, but has the disadvantage of not setting background color.

other

  • If the initialization View is not VISIBLE, use view. GONE instead of view. VISIBLE. The View set GONE will be marked when loaded, not measure.

  • Reducing the impact of alpha on performance For an opaque View, it only needs to be rendered once, but if the View is set to alpha, it will need to be rendered at least twice. The reason is that the view that contains alpha needs to know in advance what the next element of the blending view will be, and then Blend with the upper view and set it.

  • TextView sets text and images to reduce View parsing load

  • Use TextView to set the newline function, for example:

<TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Line 1 \ Line 2" />
Copy the code
  • To determine high wide View or ViewGroup, use high fixed width or match_parent as far as possible, for example: recyclerview if Item height is fixed, can use recyclerview. SetHasFixedSize (true); To prevent requestLayout from wasting resources;

P.S.

The UI rendering blog.csdn.net/lmj62356579… The UI caton optimization blog.csdn.net/joye123/art… The UI optimization tools Lint blog.csdn.net/luzhenyuxfc… The UI optimization tools Hierarchy Viewer www.jianshu.com/p/e9e05ce5b… Github.com/romainguy/V…