blob: c5e5e9095a98b82f1bc252247e9b9cfd8f810b25 [file] [log] [blame]
Dirk Dougherty22558d02009-12-10 16:25:06 -08001page.title=Window Backgrounds & UI Speed
Scott Main796ce772011-02-16 10:04:45 -08002parent.title=Articles
3parent.link=../browser.html?tag=article
Dirk Dougherty22558d02009-12-10 16:25:06 -08004@jd:body
5
6<p>Some Android applications require to squeeze every bit of performance out of
7the UI toolkit and there are many ways to do so. In this article, you will
8discover how to speed up the drawing and the <em>perceived</em> startup time of
9your activities. Both these techniques rely on a single feature, the window's
10background drawable.</p>
11
12<p>The term <em>window background</em> is a bit misleading, however. When you
13setup your user interface by calling <code>setContentView()</code> on an
14{@link android.app.Activity}, Android adds your views to the <code>Activity</code>'s
15window. The window however does not contain only your views, but a few others
16created for you. The most important one is, in the current implementation used
17on the T-Mobile G1, the <code>DecorView</code>, highlighted in the view
18hierarchy below:</p>
19
20<div style="text-align: center;"><img src="images/window_background_root.png" alt="A typical Android view hierarchy"></div>
21
22<p>The <code>DecorView</code> is the view that actually holds the
23window's background drawable. Calling
24{@link android.view.Window#setBackgroundDrawable(android.graphics.drawable.Drawable) getWindow().setBackgroundDrawable()}
25from your <code>Activity</code> changes the background of the window by changing
26the <code>DecorView</code>'s background drawable. As mentioned before, this
27setup is very specific to the current implementation of Android and can change
28in a future version or even on another device.</p>
29
30<p>If you are using the standard Android themes, a default background drawable
31is set on your activities. The standard theme currently used on the T-Mobile G1
32uses for instance a {@link android.graphics.drawable.ColorDrawable}. For most
33applications, this background drawable works just fine and can be left alone. It
34can however impacts your application's drawing performance. Let's take the
35example of an application that always draws a full screen opaque picture:</p>
36
37<div style="text-align: center;"><img src="images/window_background.png" alt="An opaque user interface doesn't need a window background"></div>
38
39<p>You can see on this screenshot that the window's background is invisible,
40entirely covered by an <code>ImageView</code>. This application is setup to
41redraw as fast as it can and draws at about 44 frames per second, or 22
42milliseconds per frame (<strong>note:</strong> the number of frames per second
43used in this article were obtained on a T-Mobile G1 with my finger on the screen
44so as to reduce the drawing speed which would otherwise be capped at 60 fps.) An
45easy way to make such an application draw faster is to <em>remove</em> the
46background drawable. Since the user interface is entirely opaque, drawing the
47background is simply wasteful. Removing the background improves the performance
48quite nicely:</p>
49
50<div style="text-align: center;"><img src="images/window_background_null.png" alt="Remove the background for faster drawing"></div>
51
52<p>In this new version of the application, the drawing speed went up to 51
53frames per second, or 19 milliseconds per frame. The difference of 3
54milliseconds per is easily explained by the speed of the memory bus on the
55T-Mobile G1: it is exactly the time it takes to move the equivalent of a
56screenful of pixels on the bus. The difference could be even greater if the
57default background was using a more expensive drawable.</p>
58
59<p>Removing the window's background can be achieved very easily by using
60a custom theme. To do so, first create a file called
61<code>res/values/theme.xml</code> containing the following:</p>
62
63<pre class="prettyprint">&lt;resources&gt;
64 &lt;style name="Theme.NoBackground" parent="android:Theme"&gt;
65 &lt;item name="android:windowBackground"&gt;@null&lt;/item&gt;
66 &lt;/style&gt;
67&lt;/resources&gt;</pre>
68
69<p>You then need to apply the theme to your activity by adding the attribute
70<code>android:theme="@style/Theme.NoBackground"</code> to your
71<code>&lt;activity /&gt;</code> or <code>&lt;application /&gt;</code> tag. This
72trick comes in very handy for any app that uses a <code>MapView</code>, a
73<code>WebView</code> or any other full screen opaque view.</p>
74
75<p><strong>Opaque views and Android</strong>: this optimization is currently
76necessary because the Android UI toolkit is not smart enough to prevent the
77drawing of views hidden by opaque children. The main reason why this
78optimization was not implemented is simply because there are usually very few
79opaque views in Android applications. This is however something that I
80definitely plan on implementing as soon as possible and I can only apologize for
81not having been able to do this earlier.</p><p>Using a theme to change the
82window's background is also a fantastic way to improve the <em>perceived</em>
83startup performance of some of your activities. This particular trick can only
84be applied to activities that use a custom background, like a texture or a logo.
85The <a href="http://code.google.com/p/shelves">Shelves</a> application is a good
86example:</p>
87
88<div style="text-align: center;"><img src="images/shelves2.png" alt="Textured backgrounds are good candidates for window's background"></div>
89
90<p>If this application simply set the wooden background in the XML layout or in
91<code>onCreate()</code> the user would see the application startup with the
92default theme and its dark background. The wooden texture would only appear
93after the inflation of the content view and the first layout/drawing pass. This
94causes a jarring effect and gives the user the impression that the application
95takes time to load (which can actually be the case.) Instead, the application
96defines the wooden background in a theme, picked up by the system as soon as the
97application starts. The user never sees the default theme and gets the
98impression that the application is up and running right away. To limit the
99memory and disk usage, the background is a tiled texture defined in
100<code>res/drawable/background_shelf.xml</code>:</p>
101
102<pre class="prettyprint">&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
103 android:src="@drawable/shelf_panel"
104 android:tileMode="repeat" /&gt;</pre><p>This drawable is simply referenced by the theme:</p>
105
106<pre class="prettyprint">&lt;resources&gt;
107 &lt;style name="Theme.Shelves" parent="android:Theme"&gt;
108 &lt;item name="android:windowBackground"&gt;@drawable/background_shelf&lt;/item&gt;
109 &lt;item name="android:windowNoTitle"&gt;true&lt;/item&gt;
110 &lt;/style&gt;
111&lt;/resources&gt;</pre>
112
113<p>The same exact trick is used in the <em>Google Maps application that ships
114with the T-Mobile G1. When the application is launched, the user immediately
115sees the loading tiles of <code>MapView</code>. This is only a trick, the theme
116is simply using a tiled background that looks exactly like the loading tiles of
117<code>MapView</code>.</em></p>
118
119<p>Sometimes the best tricks are also the simplest, so the next time you create
120an activity with an opaque UI or a custom background, remember to change the
121window's background.</p>
122
123<p><a href="http://progx.org/users/Gfx/android/WindowBackground">Download the source code of the first example</a>.</p>
124
125<p><a href="http://code.google.com/p/shelves/">Download the source code of Shelves</a>.</p>
126
127