Android BadTokenException 问题解决
前言
问题分析
android.view.WindowManager$BadTokenException,ViewRootImpl.java,android.view.ViewRootImpl,setView,640,android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@444628b8 is not valid, is your activity running?通过日志,可以知道,这种问题一般是因为在AsyncTask中的onPostExecute中执行了启动Dialog操作,但是当前的Activity已经被销毁了,写一个错误代码复现一下该问题:
package com.example.testlibrary; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.AsyncTask; import android.os.Bundle; public class MainActivity extends Activity { private UpdateUIAsyncTask asyncTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); updateUIProcess(); } private void updateUIProcess() { asyncTask = new UpdateUIAsyncTask(); asyncTask.execute(); } private class UpdateUIAsyncTask extends AsyncTask<Void, Void, Boolean> { @Override protected void onPostExecute(Boolean result) { if (!isCancelled() && result) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) .setTitle("标题") .setMessage("这是内容") .setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); AlertDialog dialog = builder.create(); dialog.show(); } } @Override protected Boolean doInBackground(Void... params) { if (!isCancelled()) { try { Thread.sleep(6000); } catch (InterruptedException e) { return false; } return true; } return true; } } }启动应用程序,并且在6s以内退出应用程序,返回建即可,就会发现应用程序出现了异常:
解决方案
android.view.WindowManager$BadTokenException: Unable to add window — token android.os.BinderProxy@4272a800 is not valid; is your activity running?.解决方法也很简单:在alertDialog.show()执行之前,判断当前的Activity是否已经销毁了,可以使用android提供的isFinishing()方法。同时,在Activity中也应该增加清理AsyncTask的操作,示例代码如下:
package com.example.testlibrary; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.AsyncTask; import android.os.Bundle; public class MainActivity extends Activity { private UpdateUIAsyncTask asyncTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); updateUIProcess(); } @Override protected void onDestroy() { // 增加清理AysncTask操作 if (asyncTask != null && asyncTask.getStatus() != AsyncTask.Status.FINISHED) { asyncTask.cancel(true); } super.onDestroy(); } private void updateUIProcess() { asyncTask = new UpdateUIAsyncTask(); asyncTask.execute(); } private class UpdateUIAsyncTask extends AsyncTask<Void, Void, Boolean> { @Override protected void onPostExecute(Boolean result) { // show dialog之前增加判断当前Activity是否finish操作 if (!isCancelled() && result && MainActivity.this != null && !MainActivity.this.isFinishing()) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) .setTitle("标题") .setMessage("这是内容") .setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); AlertDialog dialog = builder.create(); dialog.show(); } } @Override protected Boolean doInBackground(Void... params) { if (!isCancelled()) { try { Thread.sleep(6000); } catch (InterruptedException e) { return false; } return true; } return true; } } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。