How to Avoid Overdraw and androidoverdraw during android Performance Optimization
What is Overdraw? Overdraw indicates over-drawing.
How can we eliminate overdraw? The general principle is to avoid overlapping and invisible elements. Based on this principle, we can come up with the following steps:
Step 1: properly select the control container
Since overdraw has repeatedly drawn pixels in the same area, the first thing we think of is to solve the layout problem. The Layout controls provided by Android mainly include LinearLayout, TableLayout, FrameLayout, and RelativeLayout. As the saying goes, there are many things in Rome. We can use different container controls to express the same interface, but the complexity of each container control's interface description is different. In general, LinearLayout is the easiest and RelativeLayout is more complex. However, LinearLayout can only be used to describe controls that are arranged consecutively in one direction, while RelativeLayout can be used to describe interfaces with any complexity. But I want to talk about it again. The performance of container controls with higher expressive power is usually slightly lower, because the system needs to spend more time on the location of the computing child control. To sum up, LinearLayout is easy to use, efficient, and expressive. RelativeLayout is complex, with strong expressiveness and low efficiency.
For the same interface, developers should consider using RelativeLayout with as few as possible and strong table ability as containers, or using multiple LinearLayout with weak presentation capabilities. From the perspective of overdraw reduction, LinearLayout will increase the level of the number of controls. Naturally, RelativeLayout is better, however, when using LinearLayout on a certain interface does not bring more control numbers and control levels than RelativeLayout, LinearLayout is the first choice. Therefore, when expressing the interface, as a forward-looking developer, you should select the appropriate container control based on the actual situation to avoid overdraw while ensuring performance.
Step 2: remove the Default background of window
When we use some themes that come with Android, the window will be added with a solid background by default, which is held by DecorView. When we add a background image or set the background color for the custom layout, the background of DecorView is useless, but it generates an Overdraw, rendering Performance Loss. You can call this function after setContentView () in onCreate () to remove the window background.
getWindow().setBackgroundDrawable(null);
Or add
android:windowbackground="null";
Step 3: Remove unnecessary background
Sometimes for convenience, Layout will first set an overall background, and then the background for the sub-View. This will also cause overlap. If the sub-View width is mach_parent, you can see that it completely covers part of Layout, here, you can set the background to reduce the re-painting. For example, if the selector background is used, setting the normal color to "@ android: color/transparent" can also solve the problem. Here, we only give two simple examples. Some habitual mindset during the development process will lead to inadvertent Overdraw, so when we set a background for a View or ViewGroup during the development process, first, think about whether it is really necessary, or whether the background can be set on the subview in segments, instead of directly setting the graph on the Root View.
Step 4: ClipRect & QuickReject
To solve the Overdraw problem, the Android system will minimize the consumption by avoiding the rendering of completely invisible components. However, unfortunately, for custom views that are too complex (the onDraw method is often rewritten), the Android system cannot detect what operations will be performed in onDraw, overdraw cannot be avoided because the system cannot monitor and automatically optimize it. However, we can use canvas. clipRect () to help the system identify visible areas. This method can specify a rectangular area, which is drawn only in this area, and other areas will be ignored. This API can help custom views with multiple groups of overlapping components to control the display area. At the same time, the clipRect method can also help to save CPU and GPU resources. Drawing commands outside the clipRect area will not be executed, and those components whose content is in the rectangle area will still be drawn. In addition to the clipRect method, we can also use canvas. quickreject () to determine whether it is not intersecting with a rectangle, thus skipping the painting operations in non-rectangular areas.
Step 5: ViewStub
What is ViewStub? Summary:Efficient placeholder.
We often encounter this situation. The runtime dynamically determines which View or layout to display based on the conditions. A common practice is to write all views on it. First, set their visibility to View. GONE, and then dynamically change its visibility in the code. This method has the advantages of simple logic and flexible control. However, it consumes resources. Although the initial View is visible to View. GONE, the View is still Inflate during the Inflate layout, that is, the object will be created, instantiated, and set attributes. That is to say, it will consume memory and other resources.
We recommend that you use android. view. ViewStub. ViewStub is a lightweight View that is invisible and occupies very small resources. You can specify a layout for ViewStub. In the Inflate layout, only ViewStub will be initialized. Then, when ViewStub is set to visible, or ViewStub is called. when inflate () is used, the layout directed by ViewStub will be Inflate and instantiated, and the layout attribute of ViewStub will be transmitted to the layout pointed to by it. In this way, ViewStub can be used to conveniently display a layout during running.
<ViewStub android:id="@+id/stub_view" android:inflatedId="@+id/panel_stub" android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom"/>
When you want to load the layout, you can use one of the following methods:
((ViewStub) findViewById(R.id.stub_view)).setVisibility(View.VISIBLE);View importPanel = ((ViewStub) findViewById(R.id.stub_view)).inflate();
Move 6: Merge
What is the use of Merge labels? Simple and rude answer:Kill a view level.
The role of Merge is obvious, but there are some restrictions on the use of conditions. In either case, we can use the Merge tag for container control. The first seed view does not need to specify any layout attribute for the parent view. That is to say, the parent container is only a container, and the Child view only needs to be directly added to the parent view for display. In addition, if a layout (or view) needs to be embedded in LinearLayout, and the root node of the layout (or view) is also LinearLayout, a layer of unused Nesting is added, undoubtedly, this will only slow down the program speed. At this time, if we use the merge root tag, we can avoid that problem. In addition, Merge can only be used as the root label of the XML layout. When Inflate is a layout file starting with <merge/>, you must specify a parent ViewGroup and set attachToRoot to true.
Here is a simple example:
<RelativeLayoutxmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> <TextViewandroid: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "merge label used"/> </RelativeLayout>
Load the above XML into the page. The layout level is RelativeLayout-TextView. However, in the following method, replace RelativeLayout with merge, and the level of RelativeLayout is eliminated.
<Mergexmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> <TextView android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "merge tag usage"/> </merge>
7. Use draw9patch
Add a border to the ImageView. You must have met this requirement. Generally, you can set a background image behind the ImageView to expose the border to solve the problem perfectly. At this time, the ImageView has two layers of drawable, the bottom layer only serves as the border of the image. However, the overlapping areas of the two-layer drawable are drawn twice, resulting in overdraw. Optimization solution: make the background drawable into a draw9patch, and set the overlapping parts with the foreground to transparent. Because the Android 2D Renderer optimizes the transparent area in draw9patch, this overdraw is optimized. However, the background image must be made into a draw9patch, because the Android 2D Renderer only has this optimization for the draw9patch. Otherwise, a normal Png, even if you set the middle part to transparent, this overdraw will not be reduced.
Method 8: Use Alpha with caution
If you want to perform Alpha conversion on a View, you need to first draw the View, then perform Alpha conversion, and finally draw the converted effect on the interface. In layman's terms, the current View needs to be drawn twice for Alpha conversion. we can imagine that the rendering efficiency will be greatly reduced and the time consumption will double, So Alpha should be used with caution. If Alpha conversion is required, cache can be used.
view.setLayerType(LAYER_TYPE_HARDWARE);doSmoeThing();view.setLayerType(LAYER_TYPE_NONE);
You can use setLayerType to cache the current interface in the GPU, so you do not need to draw the original interface every time, but the GPU memory is very valuable, so you need to release it immediately after use.
9. Avoid OverDesign"
Overdraw will bring a poor experience to the APP. The reason for overdraw is nothing more than Complex Layout layers, overlapping views, and overlapping backgrounds. Developers can build a View without restraint, which is nothing more than a product design without restraint. There is a saying that "from luxury to luxury, from luxury to difficult", many apps are dressed in the gorgeous overdesign, but forget that simple and easy to use is the essence of the king, complicated design does not bring a good experience to users. Instead, it will make users feel overwhelmed and the product itself may become stuck. Of course, all Optimization without business discussion is an air tower, which requires a balance between product design and complex business logic and easy-to-use interface display, instead of OverDesign.