diff options
Diffstat (limited to 'docs/html/resources/articles/window-bg-speed.jd')
-rw-r--r-- | docs/html/resources/articles/window-bg-speed.jd | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/docs/html/resources/articles/window-bg-speed.jd b/docs/html/resources/articles/window-bg-speed.jd new file mode 100644 index 0000000..bd7a303 --- /dev/null +++ b/docs/html/resources/articles/window-bg-speed.jd @@ -0,0 +1,125 @@ +page.title=Window Backgrounds & UI Speed +@jd:body + +<p>Some Android applications require to squeeze every bit of performance out of +the UI toolkit and there are many ways to do so. In this article, you will +discover how to speed up the drawing and the <em>perceived</em> startup time of +your activities. Both these techniques rely on a single feature, the window's +background drawable.</p> + +<p>The term <em>window background</em> is a bit misleading, however. When you +setup your user interface by calling <code>setContentView()</code> on an +{@link android.app.Activity}, Android adds your views to the <code>Activity</code>'s +window. The window however does not contain only your views, but a few others +created for you. The most important one is, in the current implementation used +on the T-Mobile G1, the <code>DecorView</code>, highlighted in the view +hierarchy below:</p> + +<div style="text-align: center;"><img src="images/window_background_root.png" alt="A typical Android view hierarchy"></div> + +<p>The <code>DecorView</code> is the view that actually holds the +window's background drawable. Calling +{@link android.view.Window#setBackgroundDrawable(android.graphics.drawable.Drawable) getWindow().setBackgroundDrawable()} +from your <code>Activity</code> changes the background of the window by changing +the <code>DecorView</code>'s background drawable. As mentioned before, this +setup is very specific to the current implementation of Android and can change +in a future version or even on another device.</p> + +<p>If you are using the standard Android themes, a default background drawable +is set on your activities. The standard theme currently used on the T-Mobile G1 +uses for instance a {@link android.graphics.drawable.ColorDrawable}. For most +applications, this background drawable works just fine and can be left alone. It +can however impacts your application's drawing performance. Let's take the +example of an application that always draws a full screen opaque picture:</p> + +<div style="text-align: center;"><img src="images/window_background.png" alt="An opaque user interface doesn't need a window background"></div> + +<p>You can see on this screenshot that the window's background is invisible, +entirely covered by an <code>ImageView</code>. This application is setup to +redraw as fast as it can and draws at about 44 frames per second, or 22 +milliseconds per frame (<strong>note:</strong> the number of frames per second +used in this article were obtained on a T-Mobile G1 with my finger on the screen +so as to reduce the drawing speed which would otherwise be capped at 60 fps.) An +easy way to make such an application draw faster is to <em>remove</em> the +background drawable. Since the user interface is entirely opaque, drawing the +background is simply wasteful. Removing the background improves the performance +quite nicely:</p> + +<div style="text-align: center;"><img src="images/window_background_null.png" alt="Remove the background for faster drawing"></div> + +<p>In this new version of the application, the drawing speed went up to 51 +frames per second, or 19 milliseconds per frame. The difference of 3 +milliseconds per is easily explained by the speed of the memory bus on the +T-Mobile G1: it is exactly the time it takes to move the equivalent of a +screenful of pixels on the bus. The difference could be even greater if the +default background was using a more expensive drawable.</p> + +<p>Removing the window's background can be achieved very easily by using +a custom theme. To do so, first create a file called +<code>res/values/theme.xml</code> containing the following:</p> + +<pre class="prettyprint"><resources> + <style name="Theme.NoBackground" parent="android:Theme"> + <item name="android:windowBackground">@null</item> + </style> +</resources></pre> + +<p>You then need to apply the theme to your activity by adding the attribute +<code>android:theme="@style/Theme.NoBackground"</code> to your +<code><activity /></code> or <code><application /></code> tag. This +trick comes in very handy for any app that uses a <code>MapView</code>, a +<code>WebView</code> or any other full screen opaque view.</p> + +<p><strong>Opaque views and Android</strong>: this optimization is currently +necessary because the Android UI toolkit is not smart enough to prevent the +drawing of views hidden by opaque children. The main reason why this +optimization was not implemented is simply because there are usually very few +opaque views in Android applications. This is however something that I +definitely plan on implementing as soon as possible and I can only apologize for +not having been able to do this earlier.</p><p>Using a theme to change the +window's background is also a fantastic way to improve the <em>perceived</em> +startup performance of some of your activities. This particular trick can only +be applied to activities that use a custom background, like a texture or a logo. +The <a href="http://code.google.com/p/shelves">Shelves</a> application is a good +example:</p> + +<div style="text-align: center;"><img src="images/shelves2.png" alt="Textured backgrounds are good candidates for window's background"></div> + +<p>If this application simply set the wooden background in the XML layout or in +<code>onCreate()</code> the user would see the application startup with the +default theme and its dark background. The wooden texture would only appear +after the inflation of the content view and the first layout/drawing pass. This +causes a jarring effect and gives the user the impression that the application +takes time to load (which can actually be the case.) Instead, the application +defines the wooden background in a theme, picked up by the system as soon as the +application starts. The user never sees the default theme and gets the +impression that the application is up and running right away. To limit the +memory and disk usage, the background is a tiled texture defined in +<code>res/drawable/background_shelf.xml</code>:</p> + +<pre class="prettyprint"><bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/shelf_panel" + android:tileMode="repeat" /></pre><p>This drawable is simply referenced by the theme:</p> + +<pre class="prettyprint"><resources> + <style name="Theme.Shelves" parent="android:Theme"> + <item name="android:windowBackground">@drawable/background_shelf</item> + <item name="android:windowNoTitle">true</item> + </style> +</resources></pre> + +<p>The same exact trick is used in the <em>Google Maps application that ships +with the T-Mobile G1. When the application is launched, the user immediately +sees the loading tiles of <code>MapView</code>. This is only a trick, the theme +is simply using a tiled background that looks exactly like the loading tiles of +<code>MapView</code>.</em></p> + +<p>Sometimes the best tricks are also the simplest, so the next time you create +an activity with an opaque UI or a custom background, remember to change the +window's background.</p> + +<p><a href="http://progx.org/users/Gfx/android/WindowBackground">Download the source code of the first example</a>.</p> + +<p><a href="http://code.google.com/p/shelves/">Download the source code of Shelves</a>.</p> + + |