What Triggers ANR?
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) on the UI thread so the system can't process incoming user input events. Or perhaps the app spends too much time building an elaborate in-memory structure or computing the next move in a game on the UI thread. It's always important to make sure these computations are efficient, but even the most efficient code still takes time to run.
In any situation in which your app performs a potentially lengthy operation, you should not perform the work on the UI thread, but instead create a worker thread and do most of the work there. This keeps the UI thread (which drives the user interface event loop) running and prevents the system from concluding that your code has frozen. Because such threading usually is accomplished at the class level, you can think of responsiveness as a class problem. (Compare this with basic code performance, which is a method-level concern.)
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:
No response to an input event (such as key press or screen touch events) within 5 seconds.
A
How to Avoid ANRs
Android applications normally run entirely on a single thread by default the "UI thread" or "main thread"). This means anything your application is doing in the UI 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 broadcasts.
Therefore, any method that runs in the UI thread should do as little work as possible on that thread. In particular, activities should do as little as possible to set up in key life-cycle methods such as
The most effecive way to create a worker thread for longer operations is with the
privateclassDownloadFilesTaskextendsAsyncTask{// Do the long-running work in hereprotectedLongdoInBackground(URL...urls){intcount=urls.length;longtotalSize=0;for(inti=0;i
To execute this worker thread, simply create an instance and call
newDownloadFilesTask().execute(url1,url2,url3);
Although it's more complicated than
If you implement
The specific constraint on
Tip: You can use
Reinforce Responsiveness
Generally, 100 to 200ms is the threshold beyond which users will perceive slowness in an application. As such, here are some additional tips beyond what you should do to avoid ANR and make your application seem responsive to users:
If your application is doing work in the background in response to user input, show that progress is being made (such as with a
For games specifically, do calculations for moves in a worker thread.
If your application has a time-consuming initial setup phase, consider showing a splash screen or rendering the main view as quickly as possible, indicate that loading is in progress and fill the information asynchronously. In either case, you should indicate somehow that progress is being made, lest the user perceive that the application is frozen.
Use performance tools such as Systrace and Traceview to determine bottlenecks in your app's responsiveness。