Android ANR Waiting because no window has focus问题分析

Stella981
• 阅读 1997

转自:https://www.cnblogs.com/MMLoveMeMM/articles/4849667.html

这种问题主要是发生在两个应用页面之间切换的时候,这个临界点的时候,一个页面正在起来,另外一个页面已经"压栈",即失去焦点,并且在这个页面切换的时候快速点击返回back键,按照目前android系统的约定是先判断是否有window获得focus,发送按键message必须要有有效的focus窗口来接收,否则input event消息将会在系统里面Block,一当Block,系统就开始计时(即timeout),时间一到即调用notifyANR开始处理timeout事件,表面现象APP无响应,然后崩溃掉.

分析可以参考如下 :

Ref:

http://developer.android.com/training/articles/perf-anr.html

http://stackoverflow.com/questions/3467205/android-key-dispatching-timed-out

http://blog.csdn.net/wuhengde/article/details/8007448

谷歌develop官网上对ANR触发机制是这样描述的:

此处从 角度分析下AMS和WMS是如何monitor ANR的。

Android版本:Android 5.0

分析对象:keyDispatchingTimedOut的monitor机制

1. keyDispatchingTimedOut(此处‘key‘不准确,其实是InputEvent(包含KeyEvent和TouchEvent)派发超时,当前触屏手机上,以TouchEvent/MotionEvent为主),先看下这块的类图:

可以看到真正干活的是在Native侧,由native侧monitor事件是否超时,并触发调用Java侧notifyANR逻辑。

anr monitor的大概时序如下:

ANR monitor核心工作由InputDispatcher.cpp完成,在每次派发事件时,需要进行如下判断:

1. 判断是否有focused 及focusedApplication

2. 判断前面的事件是否及时完成

对于1,一般是在启动时可能触发,比如启动时间过长,在这过程中触发keyevent或trackball motionevent, 则进行如下逻辑判断:

这种情况下,对应的ANR log如下:

Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that  eventually  a window when it finishes starting up.)

对于2,KeyEvent和MotionEvent对“及时性”的策略不同,KeyEvent需要判断上一个事件是否做完(由于涉及focus的问题,KeyEvent必须等wms处理前一个事件,才把新的事件派发过去):

checkWindowReadyForMoreInputLocked

而touchevent(touch screen,e.g.),则需判断事件等待队列里的 的事件时间是否已经过去0.5秒了,相对来说,touchevent的要求更

低些,允许的执行时延更大,此时,说明UI线程卡住了,一堆  event在等待执行,需要停止event delivery,

因此无论是keyevent(实体键输入)还是touchevent(点击view)都是因为UI线程没及时处理完前面的事件导致.

设置anr的start和timeout值,在timeout时刻唤醒事件,再依据上述条件判断是否可以event delivery,

若满足事件派发条件, 则可以走正常派发流程,否则(如UI线程卡住、UI线程抢不到CPU等), 则触发onANRLocked,后续流程如时序图所示。

我感觉上面分析比较好,比较实在.

另外附上全套android input处理流程 :

Android 5.0(Lollipop)事件输入系统(Input System) : http://blog.csdn.net/jinzhuojun/article/details/41909159

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
东方客主 东方客主
3年前
Android输入法遮挡了输入框,使用android:fitsSystemWindows="true"后界面顶部出现白条
问题1、页面布局文件:<LinearLayoutxmlns:android"http://schemas.android.com/apk/res/android"android:id"@id/layoutorderdetail"android:layoutwidth"matchparent"android:layoutheigh
编程范儿 编程范儿
3年前
Vue刷新页面有哪几种方式
在Vue项目中,刷新当前页除了window.reload(),你还能想到什么办法?而且这种办法会重新加载资源出现短暂的空白页面。体验不是很好。在某个详情页面的时候,我们经常需要通过路由中的详情id去获取内容,当我们在不同的详情页来回切换的时候,打开的页面是同一个,只是需要通过监听路由中的参数id的变化去重新请求详情接口。如果这个详情页只需要一个接口
Stella981 Stella981
3年前
Django之Django模板
1、问:html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,比如数据库字段内容为2012082616:00:00,但是页面显示的却是Aug.26,2012,4p.m.答:为了页面和数据库中显示一致,需要在页面格式化时间,需要添加<td{{dayrecord.p\_time|date:
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这