View layers for dummies

Dominik Suszczewicz
UIAndroid
Published in
4 min readJan 4, 2017

Android UI framework under the hood is very complex. There are a lot of performance optimizations that you might not event notice in your daily work. But some of them you can actually control. The knowledge about how to do it is essential when you want to build the best app on the market. This tutorial shows how Android draws views and based on that how to speed up animations using View Layers.

How Android draws views

Starting with Android Ice Cream Sandwich (API >= 14) Hardware Acceleration is enabled by default. This means that all drawing operations that are performed on a Canvas use the GPU. Let’s find out how this is done.

1. View draws on Canvas

View onDraw method is responsible for defining how View will looks like on the screen. It contains series of calls to a Canvas object. The Canvas class defines methods for drawing text, lines, bitmaps, and many other graphics primitives.

For a very simple View that displays only text its onDraw method might look similar to this.

2. Android creates Display List

Ok, but how does GPU know what do draw? Maybe calls to Canvas object are somehow executed on the GPU? No!

After execution of onDraw method Android creates internal object called a Display List. A Display List is a sequence of graphics, commands needed to be executed to render a specific View. These commands are a mixture of statements that can be directly mapped to OpenGL commands, such as translating and setting up clipping rectangles, and more complex commands such as DrawText and DrawPatch.

The Display List for our simple View above might looks similar to this:

Save 3
Translate 10.00, 15.00
DrawText 1, 5, 0x17e898
Restore
RestoreToCount 0

Every View generates its own Display List, recursively descending the View hierarchy. If a View gets invalidated due to user input events or animations, the affected Display List will be rebuilt and eventually redrawn. The root View is responsible for triggering this rebuilding of the Display List after an invalidation.

3. GPU executes drawing commands

The GPU renders the elements from the Display List to the screen.
Replaying an Display List is much more efficient than executing the View onDraw method, as the Display List lives on the native C++ side of the pipeline and is basically just a huge sequence of drawing operations.

View Layers

Now when We have basic knowledge what is going on under the hood of rendering pipeline. It’s time to introduce View Layers.

Enabling View Layers allows us to say to Android system: Hey! I don’t want to execute Display List for this View every time the screen need to be redraw. Instead I want to Cache how View looks like to some Cache and then just do copy paste from the Cache to the screen.

Types of View Layers

There are two types of View Layers:

  • hardware layer — View is drawn in GPU, cached as Texture inside GPU memory
  • software layer — View is drawn entirely in CPU (no GPU involved) cached as Bitmap inside RAM

There are some operations on Canvas that are currently not supported by GPU (full list can be find here), thats why software layer still exist.

Why should you use View Layers

You can use them to get better performance when animating complex views. Because drawing View with View Layers enabled is super fast. It’s just copy paste from the Cache. Drawing commands are executed only once.

Because you need to keep cached texture somewhere it consumes more memory on a GPU — so the general approach is to enable it before animation and disable right after animation finish.

How to enable View Layers

There are several options to enable it.

Calling directly on View object:

view.setLayerType(View.LAYER_TYPE_HARDWARE); // enable

view.setLayerType(View.LAYER_TYPE_NONE); // disable

In XML:

android:layerType="hardware"

Enable only for the time of animation:

myView.animate()
.translationX(150)
.withLayer()
.start();

About the example

In our example (video) we have two very complex views and a simple animation of switching them.

When you jump to the code of demo you will see that views with text “This view is really, really unoptimized” has a lot of children. Every children draw bitmap. That’s why is is really expensive for GPU.

Video shows animating complex views with different options.

Without View Layers

This is so laggy. Do you want to see this in your app? I don’t think so.

With View Layers enabled

View Layers are enabled for both of complex views. Animation is smooth – because UI toolkit uses cached view instead of drawing complex one every frame. Green region on the image below shows where layers are enabled.

With incorrect View Layer

This example is interesting and essential to understand how View Layers works. We enabled them but animation is janky anyway – Why? Because We Did it for incorrect View. View Layer is applied to view that is constantly changing because of the animation. If a view gets updated then Display List is be rebuild. There is no sense to cache something that is changing anyway.

View Layers are great for animation! But you should use it responsibly. I hope this post will help you with that 🙂

Github & Apk

--

--