This article has participated in the third “topic writing” track of the Denver Creators Training Camp. For details, check out: Digg Project | Creators Training Camp third is ongoing, “write” to make a personal impact.
👉 About the author
As we all know, life is a long process of constantly overcoming difficulties and reflecting on progress. In this process, there will be a lot of questions and thoughts about life, so I decided to share my thoughts, experiences and stories to find resonance!!
Focus on Android/Unity and various game development tips, as well as various resource sharing (websites, tools, materials, source code, games, etc.)
👉 about to learn
We’ll see how much we can learn!
👉 background
In the second half of the current mobile Internet, mobile phones are already a necessary device for everyone. App is the closest application to users, and the interface is the most intuitive and key part of user experience. Its fluency directly affects users’ evaluation and retention of products.
Technology is for people, and if it doesn’t give you a good experience, then the very existence of technology is debatable.
So interface performance is very important and cannot be ignored.
👉 Practice
The layout code is the most basic, but also the most important.
Let’s start with a simple example
Different shades of color to indicate overdrawing:
No color: No overdrawing, that is, a pixel is drawn once, and the display applies the original color;
Blue: 1 times overdrawn, that is, a pixel has been drawn twice;
Green: 2x overdraw, i.e. one pixel is drawn 3 times;
Light red: 3x overdrawn, i.e. one pixel has been drawn 4 times;
Deep red: 4 times overdrawn or more, that is, a pixel has been drawn 5 times or more;
😜 How to render the interface
CPU(central processing unit) : we often hear that it is the core component of a computer. It has multiple caches and branches and is suitable for complex logical operations. It is mainly responsible for calculation operations of Measure, Layout, Record and Execute
GPU(image processor): We usually say the core of the graphics card is it. Used for single structure data processing (good at graphic calculation), mainly responsible for Rasterization operation
Google’s official focus on fluency optimization is also high, with interface rendering three core Vsync, Triple Buffer and Choreographer.
Why 16ms/ why 60 frames per second
Android draws a UI frame every 16ms and does it in 16ms (1 second / 0.016 frames per second = 62.5 frames per second) about 60 times per second. This is because our brains and eyes are programmed to see continuous motion at 24Fps, and even less so at 60 FPS, while 60 FPS is much more colorful.
Once it is not drawn in time, there will be a frame drop problem, which is often said to be stuck. This is because the CPU and GPU cannot process too many things in a timely manner.
Of course, the better the device, the more processing power, the less lag, and the higher the PC for playing the game is for this reason.
So how does Android draw graphics onto the interface?
This uses the CPU/GPU up here.
The GPU is responsible for Resterization, which is the basic operation of drawing Button, Shape, Path, String, Bitmap and other components. It splits those components into different pixels for display. This is a “time consuming” operation (in the blink of an eye compared to human time), and the GPU was introduced to speed up rasterization.
The CPU computes the UI components into Polygons, textures, and hands them over to the GPU for rasterization. The process is as follows:
In order to make the App smooth, we need to complete all CPU and GPU calculation, drawing, rendering and other operations within 16ms per frame.
For those interested in learning more, check out the interface rendering container DisplayList
😜 What is overdrawing
Overdraw describes when a pixel on a screen is drawn N times in the same frame. However, we can only see the UI of the top layer, which will lead to the multi-layer UI interface is invisible to the user except the top layer, which will waste a lot of CPU and GPU resources, which is shameful.
It’s like we keep drawing on a fixed area of paper, but the top layer is closest to you, and the other layers have a ghost use?
😜 How to view draw dimensions
The development tools include Hierarchy View, Systrace, Track, etc
Real machine in the developer options: debug GPU drawing, hardware layer update, GPU view update and so on
😜 Interface optimization
There are always pain points when writing Android layouts, such as:
- 1. Some layout in many pages are used, and the style is the same, every time used to copy and paste a large section, there is no way to reuse it?
- 2. After solving the problem in 1, it is found that the reuse layout always needs an extra layer of layout, knowing that layout nesting will affect the performance.
- 3. Some layouts will only be visible when they are used, but they must be written in advance, even if they are set to Invisible or Gone, they will take up more or less memory.
First and foremost, the layout must be thought out and planned in advance at the beginning of writing so as to minimize the level of nesting. The more complex a layout is, the more likely it is to be ignored and have performance problems, so we need to know some tricks to show the layout
- 1. If the image and text are together and the text does not change dynamically, you can use the image with text directly.
- 2. Remove useless layouts and controls. If you add a background, put it on the existing layout as much as possible and reduce controls that only have background functions.
- 3. Reduce the use of transparency. Assuming #55FFFFFF and #888888 are similar in color, I recommend using the latter because the former has Alpha and the view needs to be drawn at least twice.
- 4. Remove unnecessary invisible colors, backgrounds, images, etc., and keep only the upper-layer users visible
- 5. Reduce the layout hierarchy and avoid multi-layer nesting. You are advised to use parent classes such as RelativeLayout and ConstraintLayout
- 6. The basic control LinearLayout performance is higher than the RelativeLayout.
- 7. Custom View as far as possible only update render local area, eliminate constantly all redraw.
- 8. It is recommended to use the IDE version of Lint or Ali code check plug-in, pay attention to yellow warnings and other prompts, can change change.
In addition to overdrawing, we can also use abstract layouts. They are include, Merge, and ViewStub tags. Let’s take a look at them now.
Include, by far the most common, translates to “Include” and “Include.” The best way to use it is to separate the same code into a separate XML file and Include it when you need it for a layout. Not only can you dramatically reduce the amount of code, you can just change this XML if you want to.
It has two main properties: Layout: mandatory property, ID property;
We can also override the layout properties width, margin, and visibility. However, it is important to note that overwriting either Android :layout_height or Android :layout_width alone does not work, both must be overwritten simultaneously.
There’s a lot to play with here.
The Merge is introduced
Everything has pros and cons include tags in addition to the above advantages, there is also a problem is the layout nesting. He must have a root layout, which results in the final layout having one more level of nesting.
You need to specify in advance what parent layout you want to put into the merge, and then set the control position in advance.
The advantages are obvious: it eliminates redundant hierarchies, and the tag must appear as the root node. It doesn’t take up space, it just moves the child view to where you want to nest it.
ViewStub
When writing layouts, we often encounter effects that do not have to be displayed all the time, and need to be set dynamically to invisible or gone, which can affect the speed of page loading.
The solution provided by Android is the ViewStub, which is an invisible view with a size of 0 and lazy loading that exists in the view but renders the fill view only after the setVisibility() and inflate() method calls are set to relieve the stress of initializing the loading XML layout. It’s like load balancing.
Use cases: progress bar, failed to load network, display error message and so on
It has the following three important properties:
Android: Layout: ViewStub Specifies the name of the view to be filled. It is in the form of R.layout.xx.
Android :inflateId: Overrides the parent layout ID of the populated view.
Unlike the include tag, the Android: ID attribute of the ViewStub sets the ID of the ViewStub itself, not the overriding layout ID. Make no mistake about that. In addition, the ViewStub provides an OnInflateListener interface that listens to see if the layout has been loaded.
But notice that viewstub.inflate (); Method cannot be called more than once or an exception will be thrown:
java.lang.IllegalStateException: ViewStubmusthaveanon-nullViewGroupviewParent
The reason is that the ViewStub source code calls the removeViewInLayout() method to remove itself from the layout. This tells us that the ViewStub will self-destruct after successfully populating the layout, and another call to the inflate() method will throw an IllegalStateException. At this point, if you want to display the layout again, you can call the setVisibility() method.
Viewstub.getvisibility () is always 0, so use it to determine if the display is useless. Don’t worry, the setVisibility() method actually sets the visibility of the internal view, not the ViewStub itself.
😜 Hardware acceleration principle
I believe that often see some articles that open hardware acceleration to solve the problem of the card, but what is hardware acceleration?
The main principle of hardware acceleration is to convert graphics computation that CPU is not good at into GPU-specific instructions through multiple underlying logic, so that gpus that are better at graphics computation can complete rendering.
Hardware acceleration involves two steps:
Construction phase: Iterate through all views, cache the operations that need to be drawn, and hand them off to a separate Render thread using the GPU for hardware-accelerated rendering. (This phase is built using CPU in the main thread)
Drawing stage: Call OpenGL (i.e. use GPU) to draw and render the constructed view, and the drawn content is saved in Graphic Buffer and presented to SurfaceFlinger for display. (Android 5.0+ uses the Render Thread Thread, which is responsible for UI rendering and animation.)
Hardware acceleration has good advantages, but it is not a panacea.
When we usually use it, we may directly use it in Application, which is not rigorous, because hardware acceleration cannot support all drawing operations (such as complex custom View), so it will cause certain influence:
1. Pixel dislocation and other visual problems
2. API compatibility between different device versions
The official solution to these problems is to use four levels to control whether hardware acceleration occurs.
1. Application
2. Activity- Set for individual pages
3. The level of the Window
4. Separate View level to turn off acceleration (View currently does not support dynamic hardware acceleration)
👉 other
📢 author: Kom and Kom in Kom
📢 reprint instructions – be sure to specify the source: Zhim Granular’s personal home page – column – Nuggets (juejin. Cn)
📢 welcome to like 👍 collect 🌟 message 📝