diff options
Diffstat (limited to 'docs/html/guide/practices/responsiveness.jd')
-rw-r--r-- | docs/html/guide/practices/responsiveness.jd | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/docs/html/guide/practices/responsiveness.jd b/docs/html/guide/practices/responsiveness.jd new file mode 100644 index 0000000..a00e3aa --- /dev/null +++ b/docs/html/guide/practices/responsiveness.jd @@ -0,0 +1,140 @@ +page.title=Designing for Responsiveness +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>In this document</h2> +<ol> + <li><a href="#anr">What Triggers ANR?</a></li> + <li><a href="#avoiding">How to Avoid ANR</a></li> + <li><a href="#reinforcing">Reinforcing Responsiveness</a></li> +</ol> + +</div> +</div> + +<div class="figure"> +<img src="{@docRoot}images/anr.png" alt="Screenshot of ANR dialog box" width="240" height="320"/> +<p><strong>Figure 1.</strong> An ANR dialog displayed to the user.</p> +</div> + +<p>It's possible to write code that wins every performance test in the world, +but still sends users in a fiery rage when they try to use the application. +These are the applications that aren't <em>responsive</em> enough — the +ones that feel sluggish, hang or freeze for significant periods, or take too +long to process input. </p> + +<p>In Android, the system guards against applications that are insufficiently +responsive for a period of time by displaying a dialog to the user, called the +Application Not Responding (ANR) dialog, shown at right in Figure 1. The user +can choose to let the application continue, but the user won't appreciate having +to act on this dialog every time he or she uses your application. It's critical +to design responsiveness into your application, so that the system never has +cause to display an ANR dialog to the user. </p> + +<p>Generally, the system displays an ANR if an application cannot respond to +user input. For example, if an application blocks on some I/O operation +(frequently a network access), then the main application thread won't be able to +process incoming user input events. After a time, the system concludes that the +application is frozen, and displays the ANR to give the user the option to kill +it. </p> + +<p>Similarly, if your application spends too much time building an elaborate in-memory +structure, or perhaps computing the next move in a game, the system will +conclude that your application has hung. It's always important to make +sure these computations are efficient using the techniques above, but even the +most efficient code still takes time to run.</p> + +<p>In both of these cases, the recommended approach is to create a child thread and do +most of your work there. This keeps the main thread (which drives the user +interface event loop) running and prevents the system from concluding that your code +has frozen. Since such threading usually is accomplished at the class +level, you can think of responsiveness as a <em>class</em> problem. (Compare +this with basic performance, which was described above as a <em>method</em>-level +concern.)</p> + +<p>This document describes how the Android system determines whether an +application is not responding and provides guidelines for ensuring that your +application stays responsive. </p> + +<h2 id="anr">What Triggers ANR?</h2> + +<p>In Android, application responsiveness is monitored by the Activity Manager +and Window Manager system services. Android will display the ANR dialog +for a particular application when it detects one of the following +conditions:</p> +<ul> + <li>No response to an input event (e.g. key press, screen touch) + within 5 seconds</li> + <li>A {@link android.content.BroadcastReceiver BroadcastReceiver} + hasn't finished executing within 10 seconds</li> +</ul> + +<h2 id="avoiding">How to Avoid ANR</h2> + +<p>Given the above definition for ANR, let's examine why this can occur in +Android applications and how best to structure your application to avoid ANR.</p> + +<p>Android applications normally run entirely on a single (i.e. main) thread. +This means that anything your application is doing in the main thread that +takes a long time to complete can trigger the ANR dialog because your +application is not giving itself a chance to handle the input event or Intent +broadcast.</p> + +<p>Therefore any method that runs in the main thread should do as little work +as possible. In particular, Activities should do as little as possible to set +up in key life-cycle methods such as <code>onCreate()</code> and +<code>onResume()</code>. Potentially long running operations such as network +or database operations, or computationally expensive calculations such as +resizing bitmaps should be done in a child thread (or in the case of databases +operations, via an asynchronous request). However, this does not mean that +your main thread should block while waiting for the child thread to +complete — nor should you call <code>Thread.wait()</code> or +<code>Thread.sleep()</code>. Instead of blocking while waiting for a child +thread to complete, your main thread should provide a {@link +android.os.Handler Handler} for child threads to post back to upon completion. +Designing your application in this way will allow your main thread to remain +responsive to input and thus avoid ANR dialogs caused by the 5 second input +event timeout. These same practices should be followed for any other threads +that display UI, as they are also subject to the same timeouts.</p> + +<p>You can use {@link android.os.StrictMode} to help find potentially +long running operations such as network or database operations that +you might accidentally be doing your main thread.</p> + +<p>The specific constraint on IntentReceiver execution time emphasizes what +they were meant to do: small, discrete amounts of work in the background such +as saving a setting or registering a Notification. So as with other methods +called in the main thread, applications should avoid potentially long-running +operations or calculations in BroadcastReceivers. But instead of doing intensive +tasks via child threads (as the life of a BroadcastReceiver is short), your +application should start a {@link android.app.Service Service} if a +potentially long running action needs to be taken in response to an Intent +broadcast. As a side note, you should also avoid starting an Activity from an +Intent Receiver, as it will spawn a new screen that will steal focus from +whatever application the user is currently has running. If your application +has something to show the user in response to an Intent broadcast, it should +do so using the {@link android.app.NotificationManager Notification +Manager}.</p> + +<h2 id="reinforcing">Reinforcing Responsiveness</h2> + +<p>Generally, 100 to 200ms is the threshold beyond which users will perceive +lag (or lack of "snappiness," if you will) in an application. As such, here +are some additional tips beyond what you should do to avoid ANR that will help +make your application seem responsive to users.</p> + +<ul> + <li>If your application is doing work in the background in response to + user input, show that progress is being made ({@link + android.widget.ProgressBar ProgressBar} and {@link + android.app.ProgressDialog ProgressDialog} are useful for this).</li> + <li>For games specifically, do calculations for moves in a child + thread.</li> + <li>If your application has a time-consuming initial setup phase, consider + showing a splash screen or rendering the main view as quickly as possible + and filling in the information asynchronously. In either case, you should + indicate somehow that progress is being made, lest the user perceive that + the application is frozen.</li> +</ul> |