| 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> |