您的位置:首页 > 其它

Activity在后台被回收,这个时候触发showDialog,窗体泄露,WindowManager.BadTokenException

2016-01-19 10:41 866 查看
今天在友盟上看到一个崩溃日志,如下:

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都会被主动销毁。这是另外一个问题。

        

         

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  WindowManager.BadTok