ANR : Application Not Responding
应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。
用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。
所以一个流畅的合理的应用程序中不能出现anr。
因此, 在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。
用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。
所以一个流畅的合理的应用程序中不能出现anr。
因此, 在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。
在Android里,应用程序的响应性是由Activity Manager和Window Manager系统服务监视的。
当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒。
Android应用程序通常是运行在一个单独的线程(例如,main)里。
这意味着你的应用程序所做的事情如果在 主线程里占用了太长的时间的话,就会引发ANR对话框,
因为你的应用程序并没有给自己机会来处理输入事件或者Intent广播。
这意味着你的应用程序所做的事情如果在 主线程里占用了太长的时间的话,就会引发ANR对话框,
因为你的应用程序并没有给自己机会来处理输入事件或者Intent广播。
运行在
主线程里的任何方法都尽可能少做事情。
特别是关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。
潜在的耗时操作,例如 网络或数据库操作(AsyncTask),或者高耗时的计算(如改变位图尺寸),
应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。
特别是关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。
潜在的耗时操作,例如 网络或数据库操作(AsyncTask),或者高耗时的计算(如改变位图尺寸),
应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。
然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用Thread.wait()或是Thread.sleep()。
替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。
以这种方式设计你的应用程序,
将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。
替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。
以这种方式设计你的应用程序,
将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。
IntentReceiver执行时间的特殊限制意味着它应该做:
在后台里做小的、琐碎的工作如保存设定或者注册一个Notification。
和在主线程里调用的其它方法一样, 应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。
如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个Service。
在后台里做小的、琐碎的工作如保存设定或者注册一个Notification。
和在主线程里调用的其它方法一样, 应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。
如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个Service。
也应该避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
如果你的应用程序在响应Intent广播时需要向用户展示什么,你应该使用Notification Manager来实现。
一般来说,在应用程序里,100到200ms是用户能感知阻滞的时间阈值。
因此,这里有一些额外的技巧来避免ANR,并有助于让你的应用程序看起来有响应性。
如果你的应用程序为响应用户输入正在后台工作的话,
可以显示工作的进度(ProgressBar和ProgressDialog对这种情况来说很有用)。
特别是游戏,在子线程里做移动的计算。
如果你的应用程序有一个耗时的初始化过程的话,
考虑可以显示一个Splash Screen或者快速显示主画面并异步来填充这些信息。
在这两种情况下,你都应该显示正在进行的进度,
以免用户认为应用程序被冻结了。