Activity在后台被回收,这个时候触发showDialog,窗体泄露,WindowManager.BadTokenException
2016-01-19 10:41
866 查看
今天在友盟上看到一个崩溃日志,如下:
问题原因在于,我的ExamActivity是一个拥有CountDownTimer组件来执行倒计时业务的对象,该对象源码实现可以看到是通过消息队列机制,sendMessageDelay(msg,time)来实现的,所以就有一种情况,考试ExamActivity 在后台运行,这个时候Timer还在执行倒计时,一段时间后,考试ExamActivity被系统回收掉了,倒计时还在执行,当倒计时完成后触发 onTimerFinish()方法, 这个时候如果dialog.show() 就会报该错误。是因为这个时候window与Activity分离了,造成了窗体泄露。
解决方法:
1. 判断当前Activity是否finish()了通过 isFinishing()
2. 在show时,捕获异常
示例代码如下
这样就保证了不会发生类似错误了。
总结:
当程序中有类似 postMessageDelay 这种控制dialog显示的情况时,一定要考虑到Activity被回收这种情况。另外看Activity源码 onDestory里判断所有还在运行的dialog都会被主动销毁。这是另外一个问题。
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@4394f040 is not valid; is your activity running? at android.view.ViewRootImpl.setView(ViewRootImpl.java:798) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:288) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:73) at android.app.Dialog.show(Dialog.java:287) at com.module.exam.ExamActivity$1.onTimeCountFinished(ExamActivity.java:71) at com.module.question.QuestionBaseActivity$5.onTimeCountFinished(QuestionBaseActivity.java:324) at com.utils.TimeCount.onFinish(TimeCount.java:49) at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:118) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5493) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025) at dalvik.system.NativeStart.main(Native Method)
问题原因在于,我的ExamActivity是一个拥有CountDownTimer组件来执行倒计时业务的对象,该对象源码实现可以看到是通过消息队列机制,sendMessageDelay(msg,time)来实现的,所以就有一种情况,考试ExamActivity 在后台运行,这个时候Timer还在执行倒计时,一段时间后,考试ExamActivity被系统回收掉了,倒计时还在执行,当倒计时完成后触发 onTimerFinish()方法, 这个时候如果dialog.show() 就会报该错误。是因为这个时候window与Activity分离了,造成了窗体泄露。
解决方法:
1. 判断当前Activity是否finish()了通过 isFinishing()
2. 在show时,捕获异常
示例代码如下
setTimeCountListener(new TimeCount.OnTimeCountListener() { @Override public void onTimeCountFinished() { if(!ExamActivity.this.isFinishing()){ final TipsDialog tipsDialog = new TipsDialog(ExamActivity.this); tipsDialog.oneBtn("答题时间已到,本次考试结束,请交卷", "交卷", new View.OnClickListener() { @Override public void onClick(View v) { tipsDialog.dismiss(); endExam(); } }); try { tipsDialog.show(); }catch (WindowManager.BadTokenException e){ LogUtil.e(e.toString()); } } }
这样就保证了不会发生类似错误了。
总结:
当程序中有类似 postMessageDelay 这种控制dialog显示的情况时,一定要考虑到Activity被回收这种情况。另外看Activity源码 onDestory里判断所有还在运行的dialog都会被主动销毁。这是另外一个问题。
相关文章推荐
- 是否应该使用Mysql外键?
- 网络编程归纳总结八阶段
- JAVA网络编程实现基于TCP协议的时间服务(向服务器查询当前时间)
- [图像] PCA主成份分析
- malloc和free函数详解(转载)
- 佛山Uber优步司机奖励政策(1月18日~1月24日)
- C# 向ListView中添加多列数据的方法
- 2016年DBA餐盘
- PHP得到局域网IP的函数,还不是很好用,哪位大神帮忙优化一下
- Android应用内打开QQ聊天框
- NSUserDefaults使用
- 长沙Uber优步司机奖励政策(1月18日~1月24日)
- Dijkstra算法求最短路径(java)(转)
- apache 省略index.php访问
- 【转】Oracle RAC 环境下的连接管理
- 找不到或无法加载主类(Could not find or load main class )
- python的学习资源
- spring quartz任务调度
- 基于JAVA集合框架实现一个简单的学生管理系统
- 字符串转换成整数