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