token 是怎么失效的:
-
Toast 显示会有一个时长,所以在NotificationManagerService 内也有两个超时时长,跟Toast 的duration 有关,如果Toast 的duration设置的是LONG,则为3.5 s,如果是SHORT,则为2s。
-
NotificationManagerService 会在调用Toast 的show 之后发送一个延时消息,延时时长就是超时时长,这个延时消息就是用来取消Toast 的显示,取消显示会有如下操作:
1)调用Toast 中TN 的hide 方法;
2)将相应index 的ToastRecord 从mToastQueue 队列中移除;
3)将对应的token 从WMS移除
4)如果Toast 队列不为空,显示下一个Toast -
可以看到有一步操作是移除token。所以,结论来了,当Toast 调用了show 发送了一个Message之后,UI 线程被阻塞住了,超时之后token 失效,这时show 操作接着执行addView 操作时,程序就会发现token 已失效从而抛出异常。
-
如果UI在这段时间内没有执行完,Toast.show()内部的handler message得不到执行,NotificationManageService那端会把这个Toast取消掉,同时把Toast对于的window token置为无效。等App端真正需要显示Toast时,因为window token已经失效,ViewRootImpl就抛出了上面的异常。
关于Android7.x系统Toast显示异常BadTokenException解决方案
Toast与Snackbar的那点事
Android 7.x Toast BadTokenException处理
同学,你的系统Toast可能需要修复一下