In this article, we'll cover how Android determines if an application is not responding (hereafter called ANR), the causes of ANR, and guidelines for ensuring that your application is responsive. There are a set of best practices — in addition to writing efficient Android code — that will help ensure that your application's user interface is responsive. But before delving into the details, here's a screenshot of what the dialog box created by Android when an application is not responding looks like:
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:
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.
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.
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 onCreate()
and
onResume()
. 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 Thread.wait()
or
Thread.sleep()
. Instead of blocking while waiting for a child
thread to complete, your main thread should provide a 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.
The specific constraint on IntentReciever 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 an BroadcastReceiver is short), your application should start a 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 Notification Manager.
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.
Copyright 2007 Google Inc. | Build 0.9_r1-98467 - 14 Aug 2008 18:56 |