admin管理员组文章数量:1577578
今天喜提测试给的anr , anr报错信息如下 。
Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
看到这个 anr 报错信息 ,Input事件导致的anr ,感觉和窗口没有焦点有亿点关系。
ANR 复现
先弄个透明的activity,然后通过FLAG_NOT_FOCUSABLE把window设置成不可获取焦点模式,如下。
classTransparentActivity : Activity() {
companionobject {
var activityCallBack: ActivityCallBack? = nullfunopen(activity: Activity, activityCallBack: ActivityCallBack?=null) {
TransparentActivity.activityCallBack = activityCallBack
activity.startActivity(Intent(activity, TransparentActivity::class.java))
}
}
overridefunonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityCallBack?.onCreate(this, savedInstanceState)
val window = getWindow();
window.setGravity(Gravity.START or Gravity.TOP);
val params = window.getAttributes();
params.x = 0;
params.y = 0;
params.width = 1;
params.height = 1;
window.setAttributes(params);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
)
}
}
}
funtestAnr(view: View) {
TransparentActivity.open(this)
}
复制代码
运行点击testanr按钮 , 然后按返回键。
果不其然 anr 出现了 , 看anr报错原因确实和线上的报错一模一样。
ANR 产生原因
通过复现 , 可以判断应该是窗口没有焦点 , 事件无法响应导致的ANR 。
没想到吧主线程没执行耗时操作也会导致ANR的产生 。
但是这个ANR 你在屏幕上滑动几下就可以规避了 , 如下
可以看到ANR确实没出现了 , 因为我们在屏幕上滑动 , 导致事件可以被启动它的这个Activity响应了。
先不说怎么去监控它的产生 , 先看下它产生的原理 。
Input 产生的ANR原理
说 Input 之前先说下service、broadcast、provide 的anr 原理 。service、broadcast、provide 的 anr 类似于埋炸弹和拆炸弹 , 如果在规定的时间不拆掉埋下的炸弹 , 炸弹就会boom ( 产生Anr )。
input 的anr 和 service、broadcast、provider不同 。 相比service、broadcast、provide 的埋炸弹和拆炸弹机制 ,input更像是拆弹机制。 input的超时机制并非时间到了一定就会爆炸,而是处理后续事件的过程才会去检测是否该爆炸,所以更像是扫雷的过程。input超时机制为什么是扫雷,而非定时爆炸呢?是由于对于input来说即便某次事件执行时间超过timeout时长,只要用户后续在没有再生成输入事件,则不会触发ANR。 这里的扫雷是指当前输入系统中正在处理着某个耗时事件的前提下,后续的每一次input事件都会检测前一个正在处理的事件是否超时(进入扫雷状态),检测当前的时间距离上次输入事件分发时间点是否超过timeout时长。如果没有超过timeout,则会重置ANR的timeout,从而不会爆炸。
但是有个例外,就是当窗口没有焦点的情况 ,如果窗口没有焦点但又有事件给它处理 , 在这种情况下input anr 机制也和service、broadcast、provide 差不多 (埋炸弹拆炸弹机制), 如果后续没有事件在timeout内被响应(去拆炸弹) , timeout后也会产生anr 。
anr原理大致流程可以看这张图
ANR的监控
这种ANR , 通过换掉主线程 Looper 的 Printer 方式 , 通过 Choreographer 类的 FrameCallback 方式 ,通过插桩的 方式 , 通过开一个子线程不断去轮询主线程 方式 , 统统肯定都不能监控到的 。
只有监听SIGQUIT 信号才能监控到这种ANR , 具体参考 微信 Matrix for Android
ANR的解决
就本文而言 , 让 activity 的 window 可以获取焦点这个anr就解决了 。
参考文章:
Android修炼系列(32),你理解的 ANR 监控可能一直是错的
Android ANR Waiting because no window has focus问题分析
Input系统—ANR原理分析
版权声明:本文标题:一个非耗时操作Input ANR引发的思考 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1726872662a1088002.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论