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