• Layout can be said to be the most important aspect of an APP. Users have a strong perception. No matter how your code is written, users do not know it, and users can only see and operate the APP.
  • For example, wechat, the operation of the card, the user will only feel that the phone is not good, but not wechat, but other APP cards, the user will feel that the APP is not good, rather than the phone is not good. ┏ ┓ (´ ∀ `)
  • Android performance optimization – Boot speed optimization can also be learned together.

1. Caton analysis

1.1 the refresh rate

  • Rendering performance is the primary source of performance issues that most users perceive, such as lag. From the designers’ point of view, they hope that the App can have more fashionable elements such as animation and pictures to achieve smooth user experience. But the Android system probably won’t be able to do the complicated interface rendering in time. The Android system signals VSYNC every 16ms to trigger a UI rendering. If each rendering is successful, this will achieve the 60fps required for smooth graphics. In order to achieve 60fps, this means that most of the application’s operations must be done in 16ms.
  • There are a lot of animations and videos, and video ads will be displayed when the APP is started. These are stress-free for flagship Android phones, but for old phones or entry-level phones, complicated pages require a lot of calculation, and the CPU and GPU can’t handle them, so they can’t display smoothly.

  • If one of your actions takes 24ms, the system won’t be able to render properly when it gets the VSYNC signal, and you’ll lose frames. Then the user will see the same frame for 32ms.

1.2 PerfDog

Tencent PerfDog, performance monitoring

  • As shown in the figure below, huawei P30Pro is used to check the refresh of microblog in PerfDog. When static microblog content is not swiped, the refresh rate is 0fps, while when it is swiped fast, the refresh rate is around 60fps. CPU and memory usage can also be checked.

  • In the picture below, the refresh rate is always around 60fps when playing videos on twitter.

  • In the picture below, the average APP can reach 60fps, but the camera is not. The camera takes photos at 30fps, but when taking selfies, the beauty button is turned on, and it drops to 24fps. It seems that camera plus AI beauty is more efficient.
  • Small knowledge, movies or videos watched online are generally played at 24 frames per second, which can save performance and produce good results. SONY A7M3 camera can record 120 frames in slow motion, which can be done by 4 or 5 times.

1.3 the CPU Profile

  • Android performance Optimization – Startup Speed optimization describes how to use the Profile to see how long each method takes, layout loading will also be displayed, can also be used to analyze the possible situation of lag.

2. Layout optimization

2.1 Overdrawing

  • Overdraw describes when a pixel on a screen is drawn multiple times in the same frame. In a multi-level UI structure, if the invisible UI is also drawing, this can result in some pixel areas being drawn multiple times. This wastes a lot of CPU and GPU resources.
  • Blue and green is a good situation, red is more hierarchy, in order to achieve a good effect, it will set the multi-layer layout, excessive drawing more consumption performance, and the entry machine will be stuck.

  • The mobile phone enters the developer option to debug GPU overdrawing and open the display overdrawing area.
  • The layout of shell APP is mostly blue and green, indicating that there is no excessive drawing in their APP, which is very good.

  • The list below is overdrawn, but the area is small, just the content.

  • Developer option, display layout boundaries, you can see the shell layout hierarchy is really few, very clear and neat.

  • The over-drawing area of Weibo APP basically covers the whole screen. In addition to Weibo and Wechat Taobao list apps, most of them are red. The reason may be that list apps need RecyclerView and ItemView in addition to the parent layout, which can not be avoided. But if the whole item is overdrawn, the shell is better.

  • The layout of the micro blog looks a little more complicated.

2.2 Solve overdrawing

  • 1. Compared with shell, the item of microblog is overdrawn, so when we write RecyclerView, if the background of RecyclerView parent layout, RecyclerView and Item only needs one setting, it will not render without setting the background. Otherwise you’re going to overdraw.
  • 2. Parent layout cover child layout is also as far as possible to set only one of the background, unless there is no way to all need background.
  • 3. The child view will generally overwrite the parent view after drawing, so generally choose to set the background in the child view.
  • 4. View hierarchy is reduced as much as possible. The more layers there are, the slower the drawing will be.
  • 5. Set the view transparency as little as possible. If a view has alpha set, it needs to know what the view below is, and then draw itself, which is overdrawing. If the text has transparency, you can set it in the color number.

2.3 Hierarchical Optimization

  • Android Studiol has a Layout level tool, Layout Inspector, which allows you to see the hierarchy of each page after running the app. If there are too many layers, it will definitely cause lag and slow startup. In startup optimization,
  • You can see the details of the layout tree on the left.
  • LinearLayout can be solved by ConstraintLayout. ConstraintLayout can be said to combine the advantages of LinearLayout with relative layout, which can effectively reduce the level of hierarchy.

2.4 use the merge

  • We have some general layouts that we can use to avoid duplicate code, so we can use include.
  • Merge the merge tag, however, if you merge a ViewGroup into an include, you may end up with too many levels. Instead, merge the subviews into the merge tag, so that the subviews are arranged according to the viewgroups in the external include.
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <include layout="@layout/layout_head"/> </LinearLayout> <! -- layout_head --> <? xml version="1.0" encoding="utf-8"? > <merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_head"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="text1"
        android:textSize="16sp" />
 

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="text2"
        android:textSize="16sp" />
</merge>

Copy the code
  • You can see that the view inside the merge is directly inside the LinearLayout hierarchy.

2.5 ViewStub

  • We sometimes use android:visibility to set the layout to “invisible” or “gone” as needed. Invisible and Gone are not visible, but they are initialized and occupy the memory and resources. The former still occupy the location.
  • You can wrap these views that need to be hidden with the ViewStub, which is a lightweight view that is invisible and does not consume resources, and the display is initialized only when the inflate is set.

<ViewStub
    android:id="@+id/viewStub_title"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout="@layout/layout_title"
    app:layout_constraintTop_toTopOf="parent"/ > <! -- layout_title --> <? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:orientation="horizontal">

    <ImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:id="@+id/image_back"
        android:padding="12dp"
        android:src="@drawable/ic_back" />

    <TextView
        android:layout_width="0dp"
        android:id="@+id/tv_title"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:text="title" />
</LinearLayout>
Copy the code
  • Viewstub.inflate () is displayed in the Activity, but you cannot call inflate() repeatedly; Otherwise, an exception is reported:

java.lang.NullPointerException: Attempt to invoke virtual method ‘android. View. The view of the android. The ViewStub. Inflate ()’ on a null object reference.

viewStub = findViewById(R.id.viewStub_title);
viewStub.inflate();
// Then you can initialize the view inside
ImageView ivBack = findViewById(R.id.image_back);
ivBack.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) { finish(); }}); TextView tvTitle = findViewById(R.id.tv_title);Copy the code

3. Other optimization

3.1 Do not create objects in onDraw

  • We often need to customize the view, do not create objects in the onDraw() method, because the custom view draw, will very frequently call onDraw, although the method of object creation is used up will be recycled, but frequent creation and destruction of objects will cause memory jitter and GC, and GC will be jammed.

3.2 Asynchronous loading layout

Google Asynclayoutinflater library

  • LayoutInflater loads AN XML layout using IO reads the XML layout file on the main thread for XML parsing, and then uses reflection to create View/ViewGroup objects in the layout. This process naturally takes more time as the complexity of the layout increases. Android provides asynClayOutInflaters that perform time-consuming loading operations on asynchronous threads and then call back the loading results to the main thread.
  • Asynclayoutinflater
  • 1. With asynchronous constructors, the generateLayoutParams function that needs this layout parent is thread-safe.
  • 2. All views built must not create Handler or call looper. myLooper. Because it is loaded in an asynchronous thread, the asynchronous thread does not call looper.prepare by default.
  • AsyncLayoutInflater does not support LayoutInflater.Factory or LayoutInflater.Factory2. .
  • 4. Loading layouts containing Fragments is not supported.
  • 5. If AsyncLayoutInflater fails, it automatically falls back to the UI thread to load the layout.

Refer to the article

Android performance optimization paradigm