Android7.1.1 Toast 深坑

先给出异常信息图:


8E607EB3-F5BC-413a-B446-7CAC95A94DC4.png

复现步骤:
在7.1.1 复现的步骤是,在Toast.show()之后,阻塞了Handler message的处理,使用Thread.sleep(5000)。
原因是7.1.1系统对TYPE_TOAST的Window类型做了超时限制,绑定了Window Token,最长超时时间是3.5s,
PhoneWindowManager源码:


B92838B0-1320-4e85-8696-52F195C47BFC.png

如果UI在这段时间内没有执行完,Toast.show()内部的handler message得不到执行,NotificationManageService那端会把这个Toast取消掉,同时把Toast对于的window token置为无效。等App端真正需要显示Toast时,因为window token已经失效,ViewRootImpl就抛出了上面的异常。

原因:
API 25, Android 为Toast增加了一个IBinder windowToken 去处理Toast#handleShow(),从而导致了一个运行时错误:BadTokenException 。
坑的理由:
其他版本上不会出现。因为 google在该版本开始对TYPE TOAST进行管控,防止一个应用的悬浮窗一直悬浮在另一个应用上造成干扰,但是Android团队意识到这个崩溃问题,从而在API 26的时候,在Toast的内部加了try-catch保护捕获了这个错误。
目前只有7.1.1上面的Toast存在这个问题,崩溃在系统源码里。APP层可以通过自定义Toast类,反射替换TN的内部成员变量mHandler,从而添加try-catch做到workaround,所有使用Toast的地方都使用这个自定义的,不要直接使用系统原生的
具体源码对比 Toast#TN#Handler:
API 27:


2CC4867B-8A9D-4485-9497-2AE0B0AB5A0A.png

API 25:


25.png

差别还是挺大的,具体可以自己看源码分析。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,842评论 25 709
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 13,050评论 2 59
  • 前言:toast再常见不过,但是一个小小的toast居然内有乾坤,呵(w)呵(t)呵(f) 源码如下: publi...
    super超_9754阅读 1,367评论 0 0
  • 忘 却(原创) 文/徐兴映(云南) 轻轻闭上困惑的眼 回放一些精选的片段 让一地消瘦的落花 乘上愉悦之舟 驶离这个...
    小草心语阅读 151评论 1 4
  • 是一切
    懋元阅读 101评论 0 0