• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Keeping Your App Responsive
2page.tags=threads,asynctask
3
4page.article=true
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9
10<h2>In this document</h2>
11<ol class="nolist">
12  <li><a href="#anr">What Triggers ANR?</a></li>
13  <li><a href="#Avoiding">How to Avoid ANRs</a></li>
14  <li><a href="#Reinforcing">Reinforcing Responsiveness</a></li>
15</ol>
16
17<h2>You should also read</h2>
18<ul>
19  <li><a href="/topic/performance/background-optimization.html">Background Optimizations</a>
20  <li><a href="/topic/performance/scheduling.html">Intelligent Job-Scheduling</a>
21  <li><a href="/training/monitoring-device-state/manifest-receivers.html">Manipulating Broadcast Receivers On Demand</a>
22  <li><a href="/guide/components/intents-filters.html">Intents and Intent Filters</a>
23</ul>
24
25</div>
26</div>
27
28<div class="figure" style="width:280px">
29<img src="{@docRoot}images/anr.png" alt=""/>
30<p class="img-caption"><strong>Figure 1.</strong> An ANR dialog displayed to the user.</p>
31</div>
32
33<p>It's possible to write code that wins every performance test in the world,
34but still feels sluggish, hang or freeze for significant periods, or take too
35long to process input. The worst thing that can happen to your app's responsiveness
36is an "Application Not Responding" (ANR) dialog.</p>
37
38<p>In Android, the system guards against applications that are insufficiently
39responsive for a period of time by displaying a dialog that says your app has
40stopped responding, such as the dialog
41in Figure 1. At this point, your app has been unresponsive for a considerable
42period of time so the system offers the user an option to quit the app. It's critical
43to design responsiveness into your application so the system never displays
44an ANR dialog to the user. </p>
45
46<p>This document describes how the Android system determines whether an
47application is not responding and provides guidelines for ensuring that your
48application stays responsive. </p>
49
50
51<h2 id="anr">What Triggers ANR?</h2>
52
53<p>Generally, the system displays an ANR if an application cannot respond to
54user input. For example, if an  application blocks on some I/O operation
55(frequently a network access) on the UI thread so the system can't
56process incoming user input events. Or perhaps the app
57spends too much time building an elaborate in-memory
58structure or computing the next move in a game on the UI thread. It's always important to make
59sure these computations are efficient, but even the
60most efficient code still takes time to run.</p>
61
62<p>In any situation in which your app performs a potentially lengthy operation,
63<strong>you should not perform the work on the UI thread</strong>, but instead create a
64worker thread and do most of the work there. This keeps the UI thread (which drives the user
65interface event loop) running and prevents the system from concluding that your code
66has frozen. Because such threading usually is accomplished at the class
67level, you can think of responsiveness as a <em>class</em> problem. (Compare
68this with basic code performance, which is a <em>method</em>-level
69concern.)</p>
70
71<p>In Android, application responsiveness is monitored by the Activity Manager
72and Window Manager system services. Android will display the ANR dialog
73for a particular application when it detects one of the following
74conditions:</p>
75<ul>
76    <li>No response to an input event (such as key press or screen touch events)
77    within 5 seconds.</li>
78    <li>A {@link android.content.BroadcastReceiver BroadcastReceiver}
79    hasn't finished executing within 10 seconds.</li>
80</ul>
81
82
83
84<h2 id="Avoiding">How to Avoid ANRs</h2>
85
86<p>Android applications normally run entirely on a single thread by default
87the "UI thread" or "main thread").
88This means anything your application is doing in the UI thread that
89takes a long time to complete can trigger the ANR dialog because your
90application is not giving itself a chance to handle the input event or intent
91broadcasts.</p>
92
93<p>Therefore, any method that runs in the UI thread should do as little work
94as possible on that thread. In particular, activities should do as little as possible to set
95up in key life-cycle methods such as {@link android.app.Activity#onCreate onCreate()}
96and {@link android.app.Activity#onResume onResume()}.
97Potentially long running operations such as network
98or database operations, or computationally expensive calculations such as
99resizing bitmaps should be done in a worker thread (or in the case of databases
100operations, via an asynchronous request).</p>
101
102<p>The most effective way to create a worker thread for longer
103operations is with the {@link android.os.AsyncTask}
104class. Simply extend {@link android.os.AsyncTask} and implement the
105{@link android.os.AsyncTask#doInBackground doInBackground()} method to perform the work.
106To post progress changes to the user, you can call
107 {@link android.os.AsyncTask#publishProgress publishProgress()}, which invokes the
108 {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} callback method. From your
109 implementation of {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} (which
110 runs on the UI thread), you can notify the user. For example:</p>
111
112<pre>
113private class DownloadFilesTask extends AsyncTask&lt;URL, Integer, Long> {
114    // Do the long-running work in here
115    protected Long doInBackground(URL... urls) {
116        int count = urls.length;
117        long totalSize = 0;
118        for (int i = 0; i &lt; count; i++) {
119            totalSize += Downloader.downloadFile(urls[i]);
120            publishProgress((int) ((i / (float) count) * 100));
121            // Escape early if cancel() is called
122            if (isCancelled()) break;
123        }
124        return totalSize;
125    }
126
127    // This is called each time you call publishProgress()
128    protected void onProgressUpdate(Integer... progress) {
129        setProgressPercent(progress[0]);
130    }
131
132    // This is called when doInBackground() is finished
133    protected void onPostExecute(Long result) {
134        showNotification("Downloaded " + result + " bytes");
135    }
136}
137</pre>
138
139 <p>To execute this worker thread, simply create an instance and
140 call {@link android.os.AsyncTask#execute execute()}:</p>
141
142<pre>
143new DownloadFilesTask().execute(url1, url2, url3);
144</pre>
145
146
147<p>Although it's more complicated than {@link android.os.AsyncTask}, you might want to instead
148create your own {@link java.lang.Thread} or {@link android.os.HandlerThread} class. If you do,
149you should set the thread priority to "background" priority by calling {@link
150android.os.Process#setThreadPriority Process.setThreadPriority()} and passing {@link
151android.os.Process#THREAD_PRIORITY_BACKGROUND}. If you don't set the thread to a lower priority
152this way, then the thread could still slow down your app because it operates at the same priority
153as the UI thread by default.</p>
154
155<p>If you implement {@link java.lang.Thread} or {@link android.os.HandlerThread},
156be sure that your UI thread does not block while waiting for the worker thread to
157complete&mdash;do not call {@link java.lang.Thread#wait Thread.wait()} or
158{@link java.lang.Thread#sleep Thread.sleep()}. Instead of blocking while waiting for a worker
159thread to complete, your main thread should provide a {@link
160android.os.Handler} for the other threads to post back to upon completion.
161Designing your application in this way will allow your app's UI thread to remain
162responsive to input and thus avoid ANR dialogs caused by the 5 second input
163event timeout.</p>
164
165<p>The specific constraint on {@link android.content.BroadcastReceiver} execution time
166emphasizes what broadcast receivers are meant to do:
167small, discrete amounts of work in the background such
168as saving a setting or registering a {@link android.app.Notification}. So as with other methods
169called in the UI thread, applications should avoid potentially long-running
170operations or calculations in a broadcast receiver. But instead of doing intensive
171tasks via worker threads, your
172application should start an {@link android.app.IntentService} if a
173potentially long running action needs to be taken in response to an intent
174broadcast.</p>
175
176<p>
177  Another common issue with {@link android.content.BroadcastReceiver} objects
178  occurs when they execute too frequently. Frequent background execution can
179  reduce the amount of memory available to other apps.
180  For more information about how to enable and disable
181  {@link android.content.BroadcastReceiver} objects efficiently, see
182  <a href="/training/monitoring-device-state/manifest-receivers.html">Manipulating
183    Broadcast Receivers on Demand</a>.
184</p>
185
186<p class="note"><strong>Tip:</strong>
187You can use {@link android.os.StrictMode} to help find potentially
188long running operations such as network or database operations that
189you might accidentally be doing on your main thread.</p>
190
191
192
193<h2 id="Reinforcing">Reinforce Responsiveness</h2>
194
195<p>Generally, 100 to 200ms is the threshold beyond which users will perceive
196slowness in an application. As such, here
197are some additional tips beyond what you should do to avoid ANR and
198make your application seem responsive to users:</p>
199
200<ul>
201    <li>If your application is doing work in the background in response to
202    user input, show that progress is being made (such as with a {@link
203    android.widget.ProgressBar} in your UI).</li>
204
205    <li>For games specifically, do calculations for moves in a worker
206    thread.</li>
207
208    <li>If your application has a time-consuming initial setup phase, consider
209    showing a splash screen or rendering the main view as quickly as possible, indicate that
210    loading is in progress and fill the information asynchronously. In either case, you should
211    indicate somehow that progress is being made, lest the user perceive that
212    the application is frozen.</li>
213
214    <li>Use performance tools such as <a href="{@docRoot}tools/help/systrace.html">Systrace</a>
215    and <a href="{@docRoot}tools/help/traceview.html">Traceview</a> to determine bottlenecks
216    in your app's responsiveness.</li>
217</ul>
218