ANR:Application Not Responding,即应用程序无响应。数据库
在Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的响应时间,若是应用程序主线程(即UI线程)在超时时间内对输入事件没有处理完毕,或者对特定操做没有执行完毕,就会出现ANR。json
对于输入事件没有处理完毕产生的ANR,Android会显示一个对话框,提示用户当前应用程序没有响应,用户能够选择继续等待或者关闭这个应用程序(也就是杀掉这个应用程序的进程)。网络
ANR通常有三种类型:app
ANR产生的常见缘由:异步
能够从log中搜索“ANR in”或“am_anr”,会找到ANR发生的log,该行会包含了ANR的时间、进程、是何种ANR等信息。ide
ANR产生时,系统会生成一个traces.txt的文件放在/data/anr/下。 能够经过adb命令将其导出到本地:
adb pull data/anr/traces.txt函数
trace文件记录了发生ANR先后该进程的各个线程的stack。oop
1.合理使用UI主线程,耗时操做放入其余线程工做。post
1.1 UI线程尽可能只作跟UI相关的工做。spa
1.2 耗时的工做(好比数据库操做,I/O,链接网络或者别的有可能阻碍UI线程的操做)把它放入单独的线程处理。
2.尽可能用Handler来处理UI thread和别的thread之间的交互。
3.合理使用并遵循Android生命周期,避免在onCreate()和onResume()作过多的事情。
4.sharedPreference的使用:
4.1 sharedPreference的commit()方法是同步的,apply()方法通常是异步执行的。在主线程不要用其commit(),用apply()替换。
4.2 sharedPreference的写是全量写而非增量写,因此尽可能都修改完同一apply,避免改一点apply一次(apply()方法在Activity stop的时候主线程会等待写入完成,提交屡次就很容易卡)。而且存储文本也不宜过大,这样会很慢。另外,若是写入的是json或者xml,因为须要加和删转义符号,速度会比较慢。
5.若是主线程阻塞,开辟单独的子线程来处理耗时阻塞事务。
6.若是I/O阻塞,通常来讲就是文件读写或数据库操做执行在主线程了,能够经过开辟子线程的方式异步执行。
7.若是内存不够用,增大VM内存,使用largeHeap属性,排查内存泄露。
各个组件的生命周期函数都不该该有太耗时的操做。
Activity的全部生命周期回调、Service的onCreate()、BroadcastReceiver的onReceive(开个IntentService去执行相应操做)、
ContentProvider的onCreate()是执行在主线程的。
没有使用子线程的looper的Handler的handleMessage,
post(Runnable)是执行在主线程的。
AsyncTask的回调中除了doInBackground,其余都是执行在主线程的。
View的post(Runnable)是执行在主线程的。
一些同步的操做主线程有可能被锁,须要等待其余线程释放相应锁才能继续执行,这样会有必定的ANR风险。对于这种状况有时也能够用异步线程来执行相应的逻辑。另外, 咱们要避免死锁的发生(主线程被死锁基本就等于要发生ANR了)。