Cut to the chase

1. Write pixels multiple times

When rendering opaque pixels, only write once

Each pixel needs to be written at least twice when rendering transparent pixels

  • The first time is the previous pixel value
  • A second time blend the previous color with the set opacity to produce a new color value, and write this new color value.

What we see below one layer is another layer of translucency, which for the screen is a concrete color value mixed together.

2. Command rearrangement is invalid

The DisplayList sent to the RenderThread is executed in the View hierarchy, in the default order, but this does not perform well:

The idea of divide and conquer and merge can improve performance. Everyone has heard of reordering instructions, which is to execute the same instructions together and merge them into a single operation. In this way, the performance is definitely better.

A lot of content is drawn at once, which is very efficient. There is only one problem. In fact, in the above example, background item is not rendered at one time, because overlap appears. In order to ensure the correct alpha after overlap, rendering here can only be performed serially, but not merged.

We found that correctness is still the number one priority for the Android default; As mentioned in point 1, alpha rendering, the bottom layer of blending theory is to make rendering on the original pixels in turn.

We see that most rendering operations can enjoy the high performance of reordering and merging batching, but alpha rendering is excluded.

3. Disaster situation: Alpha rendering of ViewGroup

In animation, it is often necessary to change the transparency of the ViewGroup to fade in and out. At this point, things have changed a bit, and if we use the previous drawing method (each child View is drawn transparently), we will have a problem:

Where there is overlap, the opacity will be superimposed (right below).

We want the left side of the image below, not the right.

How should this problem be solved? The Android rendering team is certainly aware of this problem, and their solution is:

  • Draws a frame of unalpha data into memory
  • After alpha processing, render the data to the screen

This solution does solve the UI exception problem above. However, it caused a redrawing of the entire View Hierarchy, redrawing a frame of data for each alpha transformation of the ViewGroup. If I were performing an animation, wouldn’t that be a performance disaster?

So here’s the question:

Why is this frame redrawn? Isn’t that the frame you just rendered?

You are absolutely right. This frame was actually generated, but it was discarded. After all, it takes up a lot of memory, and if you don’t know whether it is useful, it is discarded by default after the meeting.

The direction of our optimization is to use cached data, space for time. The specific execution calls the following API:

//before API 16 setLayerType(View.LAYER_TYPE_HARDWARE, null); //before alpha animation setLayerType(View.LAYER_TYPE_NONE, null); / / after alpha animation. / / the from API 16 ViewPropertyAnimator alpha (0.0 f) withLayer (); //manage layer type automaticallyCopy the code

As we just mentioned, the problem is that the overlapped UI has an exception. If you are sure that there is no overlapped UI, or you can accept the resulting UI problems (for better rendering performance), you can rewrite the View’s hasOverlappingRendering method. The result returns false, which increases rendering performance.

class MyView extends View { @Override public boolean hasOverlappingRendering() { return false; }}Copy the code

The above.


Reference

www.youtube.com/watch?v=zdQ…

www.youtube.com/watch?v=wIy…