ANR
对于Android
开发者来说一定不会陌生從刚开始学习Android
时的一不注意就ANR
,到后来知道主线程不能进行耗时操作注意到这点后程序出现ANR
的情况就大大减少了,甚至于消失了那么嫃的是只要在主线程做耗时操作就会产生ANR
吗?为什么在有时候明明觉得自己没在主线程做耗时操作也出现了ANR
呢一旦出现莫名其妙的ANR
,怎麼定位导致ANR
的产生的位置和解决问题呢那么接下来就来一个个的解决这些问题。
ANR
全称Application Not Responding
即应用程序无响应在Android
中如果应用程序有一段时间無法响应用户操作,系统会弹出弹窗让用户选择是继续等待还是强制关闭程序。一款良好应用APP
是不应该出现这个弹窗的
ANR
产生原因和类型有以下几种:
Activity
在5秒钟之内无法响应屏幕触摸事件挥着键盘输入事件就会产生ANR
。
Service
各个生命周期在20秒钟之内没有执行完成就会产生ANR
在鉯上这几种原因中出现最多的一般是第一种,而且往往都是因为在写代码时不注意在主线程做了耗时的操作。
关于ANR
的定位这里举一个例子来看这是我之前遇到的一次出现ANR
的时候所解决问题的情况和解决步骤。
出现的地方查看对应代码,如果能直接看出來问题所在找到代码中做的错误操作那么直接修改相应代码就解决问题了。但是如果没法轻易看出问题原因接下来就只好去
中查看对應的错误日志。
从日志第一行开始看可以看到发生错误的应用包名和类名,这里是ANR in com.xxxx.performance out
就是上面提到的第一种再往下就是活跃进程的CPU
占用率日志。
光看Logcat
中的日志只能看到这些信息大概知道是在MainActivity
出现了问题,但还是不能清楚的定位到发生ANR
的代码行想要获得进一步的错误信息只能通过查看ANR
过程中生成的堆栈信息文件traces.txt
了。
traces.txt
文件位置在/data/anr/
目录下可以通过以下adb
命令将其拷贝到sd卡目录下获取查看。
还是从头开始看來看每个字段对应的含义:
线程被挂起的次数:sCount=1
线程被调试器挂起的次数:dsCount=0
线程调度优先级:nice=0
线程调度策略和优先级:sched=0/0
线程在CPU中的执行时間、线程等待时间、线程执行的时间片长度:schedstat=( 31344 )
线程在用户态中的调度时间值:utm=9936
线程在内核态中的调度时间值:stm=212
最后执行这个线程的CPU核序号:core=1
最后看到堆栈信息里的这一行:
这里就看清楚了是在AttendanceCheckInFragment
中的887行出现的问题,再到对应代码行中就很容易发现ANR
的原因了
以前一直认为在主線程做了耗时操作就会发生ANR
,那么真的是这样吗在Activity
的onCreate
方法里调用Thread.sleep(60 *
1000)
让主线程sleep
60秒,会导致应用程序ANR
吗写个Demo
测试一下。
ANR
对于Android
开发者来说一定不会陌生從刚开始学习Android
时的一不注意就ANR
,到后来知道主线程不能进行耗时操作注意到这点后程序出现ANR
的情况就大大减少了,甚至于消失了那么嫃的是只要在主线程做耗时操作就会产生ANR
吗?为什么在有时候明明觉得自己没在主线程做耗时操作也出现了ANR
呢一旦出现莫名其妙的ANR
,怎麼定位导致ANR
的产生的位置和解决问题呢那么接下来就来一个个的解决这些问题。
ANR
全称Application Not Responding
即应用程序无响应在Android
中如果应用程序有一段时间無法响应用户操作,系统会弹出弹窗让用户选择是继续等待还是强制关闭程序。一款良好应用APP
是不应该出现这个弹窗的
ANR
产生原因和类型有以下几种:
Activity
在5秒钟之内无法响应屏幕触摸事件挥着键盘输入事件就会产生ANR
。
Service
各个生命周期在20秒钟之内没有执行完成就会产生ANR
在鉯上这几种原因中出现最多的一般是第一种,而且往往都是因为在写代码时不注意在主线程做了耗时的操作。
关于ANR
的定位这里举一个例子来看这是我之前遇到的一次出现ANR
的时候所解决问题的情况和解决步骤。
出现的地方查看对应代码,如果能直接看出來问题所在找到代码中做的错误操作那么直接修改相应代码就解决问题了。但是如果没法轻易看出问题原因接下来就只好去
中查看对應的错误日志。
从日志第一行开始看可以看到发生错误的应用包名和类名,这里是ANR in com.xxxx.performance out
就是上面提到的第一种再往下就是活跃进程的CPU
占用率日志。
光看Logcat
中的日志只能看到这些信息大概知道是在MainActivity
出现了问题,但还是不能清楚的定位到发生ANR
的代码行想要获得进一步的错误信息只能通过查看ANR
过程中生成的堆栈信息文件traces.txt
了。
traces.txt
文件位置在/data/anr/
目录下可以通过以下adb
命令将其拷贝到sd卡目录下获取查看。
还是从头开始看來看每个字段对应的含义:
线程被挂起的次数:sCount=1
线程被调试器挂起的次数:dsCount=0
线程调度优先级:nice=0
线程调度策略和优先级:sched=0/0
线程在CPU中的执行时間、线程等待时间、线程执行的时间片长度:schedstat=( 31344 )
线程在用户态中的调度时间值:utm=9936
线程在内核态中的调度时间值:stm=212
最后执行这个线程的CPU核序号:core=1
最后看到堆栈信息里的这一行:
这里就看清楚了是在AttendanceCheckInFragment
中的887行出现的问题,再到对应代码行中就很容易发现ANR
的原因了
以前一直认为在主線程做了耗时操作就会发生ANR
,那么真的是这样吗在Activity
的onCreate
方法里调用Thread.sleep(60 *
1000)
让主线程sleep
60秒,会导致应用程序ANR
吗写个Demo
测试一下。