背景:
只有主线程才可以更新ui,因为为了防止多线程访问变量导致错误的问题,所以更新ui全部是在主线程中。我们可以通过handler 或者view 的post 的方法进行更新,还有runinUiThread等。
github: https://github.com/kodulf/ANRDemo
发生原因:
主线程执行时间超过5秒钟,broadcast 的onReceiver 方法执行超过了10秒钟,service 执行时间超过了15秒
Activity----->5秒
Broadcast----->10秒
Service----->20秒
会报ANR,都是在主线程中运行的
可能是下载的操作是在主线程直接进行操作了,例如broadcast的onreceiver 里面执行的时间太长了,service
举个例子:
比方kfc, 前面点餐员,如果你还让点餐员去给你拿餐,人少的时候还可以,可以快速的响应你,如果人多的时候,那么,可能就会出现后台做不过来,需要点餐员在那边等着然后才能给你拿。
正确的做法应该是,点餐员就负责给你点餐,然后后面有专门的人负责给你去餐,点完餐在旁边等待就好了,不要打扰后面的人点餐。
解决思路:
1: 当前的怎么check log
如果出现了anr,那么会有两个地方的log,
1.1 首先就是logcat 里面的log,我们可以定位到线程的id号
1.2 在/data/anr/下面会有具体的anr的日志。这个可以定位到具体的是哪一个线程,哪一行报的错
但是在user版本上面(不可以root),我们是访问不到这个路径的, 那么我们可以通过adb bugreport 来将当前的bug内容集中起来,然后将该包复制到本地解压后,找到路径FS->data->anr 这里的FS 应该就是filesystem的缩写吧。
例如1.1 上面定位到了pid 为2008, 那么 在这个文件里面搜索这个pid ,我们可以定位到相应的suspend 类似的信息,
2: 怎么debug
如果要去debug当前的一些方法执行了多长时间,那么我们可以有3种方法获取到相应的trace文件:
第一获取trace文件的方法,在方法里面添加
Debug.startMethodTrace(“customer”)
Debug.stopMethodTrace()
如果是使用Debug.startMethodTrace(“test”) 一般保存在sdcard 里面,
第二个获取trace的方法,在profile的时候点击cpu,
第三发获取trance 的方法,可以通过monitor 里面的两个地方获取,
获取第一个,点击profile 打开后, monitor 那边的就可以显示红色了
获取第二个,点击图表的图片,会生成一个5秒的trace文件。
通过trace文件我们可以定位到某一个方法到底使用了多长时间。
具体的可以去参考里面看
参考:
https://v.youku.com/v_show/id_XNzIxNjM1NDg4.html?from=y1.7-2
https://blog.youkuaiyun.com/Rodulf/article/details/50585174
https://blog.youkuaiyun.com/yinzhijiezhan/article/details/80167283
https://www.jianshu.com/p/fa962a5fd939
https://www.jianshu.com/p/5efbc1603a4a
-------------------------------------------------draft--------------------------------
为什么只有一个线程才能更新ui, 为了防止多线程导致数据的错误。所以所有的ui更新都是通过主线程来做的。
只有一个线程可以修改ui资源
主线程的代码阻塞了,那么代码将会无法响应
这种卡住的行为就是anr,
如果主线程超过5秒没有响应
is not response。
其实不是为了说 为了防止anr,而做一些操作,而是为了给用户更好的体验,例如按钮的点击,如果出现了sleep10秒的话,那么就会出现点击然后没有回弹的,没有反应的情况,所以anr 的出现主要是给用户很差的体验,体验非常的糟糕
耗时操作是不可能避免的
1: 网络链接和网络数据的获取,例如获取图片,理想情况下可能几十毫秒。
2: 对存储器的读写
3: 大量的数据的计算,获取全部应用的界面
可能网络不稳定, 磁盘在忙,cpu 被占用。
所以如果需要网络链接或者是读取数据,最好是在子线程中去执行。 然后
任何阻塞的操作都是有阻塞超过5秒的可能, 即便是小于5秒,也会导致某个时间里面用户无法操作的
ui主线程负责事件的监听和绘制,因此,必须要保证ui线程能够随时响应用户的需求
如果是使用Debug.startMethodTrace(“test”) 一般保存在sdcard 里面,
所以说耗时操作不要在主线程执行的原因就是这个了。
traceview
https://blog.youkuaiyun.com/yinzhijiezhan/article/details/80167283
点击profile 打开后, monitor 那边的就可以显示红色了
二.ANR机制的实现原理:
文章:http://gityuan.com/2016/07/02/android-anr/从源码角度详细的分析了ANR机制实现的原理。对于上一章讲到的1-4中情况,分别找到了其源码中是如何实现的,对于每一种大概原理如下:1.在进行相关操作调用hander.sendMessageAtTime()发送一个ANR的消息,延时时间为ANR发生的时间(如前台Service是当前时间20s之后)。2.进行相关的操作3.操作结束后向remove掉该条message。如果相关的操作在规定时间没有执行完成,该条message将被handler取出并执行,就发生了ANR。
下面以BroadcastReceiver为例详细介绍:
BroadcastQueue.processNextBroadcast()
4019



被折叠的 条评论
为什么被折叠?



