- BUG出现场景:在二次弹出自定义对话框的时候抛出的异常
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@406ab4c8 is not valid
at android.view.ViewRoot.setView(ViewRoot.java:532)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:200)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:114)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.app.Dialog.show(Dialog.java:241)
at android.app.AlertDialog$Builder.show(AlertDialog.java:802)
- 这个BUG网上的解决方案真是特别的多。要么是使用
getParent()
代替当前的Activity.this
; - 要么是在对话框弹出之前,进行
activity.this.isFinish(
)判断一下。但是很不幸,这两种解决方式都不能解决我的问题。
- 先说第一种,使用
Activity.this.getParent()
。很不幸,这个方法的返回值只有在当前Activity
继承自android.app.ActivityGroup
才不返回null
.所以,对我无效。 - 再说第二种,看起来有道理的样子,但是我加上这个判断之后,错误依然存在,没有解决我的问题。
- 然后我找了很久,一直没有找到我的问题的解决方式。后来无意中发现了问题出在了我的单例模式的工具类上面。
- 我将弹出自定义对话框的代码放进了一个单例的工具类中,以为很牛逼,很高大上。但是问题就出现在单例模式上。单例获取的对象永远是唯一对象,且
final
过,也就是说,App不结束,这个对象是不会被回收的。也不能手动置空。但是Activity
是很脆弱的,一下就挂了。所以,正确的做法就是,在Activity
销毁的时候,销毁这个对话框的工具类对象,这样就OK了。【实际上不去在销毁Activity的时候,手动置空该工具类对象也是OK的,应该是Activity在销毁的时候,会干掉自己的成员变量的吧,不清楚….】
正确调用方式:
public class SecondActivity extends Activity {
private Context context;
private List<Bean> data;
private MydialogUtils mydialogUtils;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
context = this;
mydialogUtils = new MydialogUtils();
data = new ArrayList<Bean>();
data.add(new Bean("local system db", false));
data.add(new Bean("local system file", true));
data.add(new Bean("local private db", false));
data.add(new Bean("local private file", true));
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mydialogUtils.showMyDialog(context, data);
}
});
}
@Override
protected void onDestroy() {
mydialogUtils.destoryMydialog();
super.onDestroy();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
mydialogUtils
一定要是一个普通的对象,不要是一个单例对象,或者一个死不掉的对象。!!!!
对话框的工具类:
public class MydialogUtils {
public static final MydialogUtils UTILS = new MydialogUtils()
private View dialogView
private AlertDialog mDialog
public static MydialogUtils getInstance() {
return UTILS
}
public void showMyDialog(final Context context, final List<Bean> data) {
Log.e("aaa", "aaa-->openMydialog")
AlertDialog.Builder builder = new AlertDialog.Builder(context)
if (dialogView == null) {
dialogView = View.inflate(context, R.layout.dialog_layout, null)
}
builder.setView(dialogView)
final TextView tvTitle = (TextView) dialogView
.findViewById(R.id.tvTitle)
final TextView tv0 = (TextView) dialogView.findViewById(R.id.tv0)
final TextView tv1 = (TextView) dialogView.findViewById(R.id.tv1)
final TextView tv2 = (TextView) dialogView.findViewById(R.id.tv2)
final TextView tv3 = (TextView) dialogView.findViewById(R.id.tv3)
final CheckBox cb0 = (CheckBox) dialogView.findViewById(R.id.cb0)
final CheckBox cb1 = (CheckBox) dialogView.findViewById(R.id.cb1)
final CheckBox cb2 = (CheckBox) dialogView.findViewById(R.id.cb2)
final CheckBox cb3 = (CheckBox) dialogView.findViewById(R.id.cb3)
final View layout0 = dialogView.findViewById(R.id.tv0Layout)
final View layout1 = dialogView.findViewById(R.id.tv1Layout)
final View layout2 = dialogView.findViewById(R.id.tv2Layout)
final View layout3 = dialogView.findViewById(R.id.tv3Layout)
tv0.setText(data.get(0).getStr())
tv1.setText(data.get(1).getStr())
tv2.setText(data.get(2).getStr())
tv3.setText(data.get(3).getStr())
cb0.setChecked(data.get(0).isCheck())
cb1.setChecked(data.get(1).isCheck())
cb2.setChecked(data.get(2).isCheck())
cb3.setChecked(data.get(3).isCheck())
layout0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Bean bean = data.get(0)
bean.setCheck(!bean.isCheck())
cb0.setChecked(bean.isCheck())
}
})
layout1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Bean bean = data.get(1)
bean.setCheck(!bean.isCheck())
cb1.setChecked(bean.isCheck())
}
})
layout2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Bean bean = data.get(2)
bean.setCheck(!bean.isCheck())
cb2.setChecked(bean.isCheck())
}
})
layout3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Bean bean = data.get(3)
bean.setCheck(!bean.isCheck())
cb3.setChecked(bean.isCheck())
}
})
final TextView tvCancel = (TextView) dialogView
.findViewById(R.id.tvCancel)
final TextView tvOK = (TextView) dialogView.findViewById(R.id.tvOK)
tvCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
initData(data)
closeMyDialog()
}
})
tvOK.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.v("aaa", "#####start")
for (Bean bean : data) {
Log.e("aaa", "" + bean)
}
Log.v("aaa", "#####start")
// Log.e("aaa", "all-->" + data)
closeMyDialog()
}
})
if (mDialog == null)
mDialog = builder.create()
mDialog.show()
}
public void closeMyDialog() {
if (mDialog != null && mDialog.isShowing())
mDialog.dismiss()
}
private void initData(List<Bean> data) {
if (data != null) {
data.clear()
data.add(new Bean("local system db", false))
data.add(new Bean("local system file", true))
data.add(new Bean("local private db", false))
data.add(new Bean("local private file", true))
}
}
public void destoryMydialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss()
}
mDialog = null
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
工具类有点麻烦,不用去看,就是不要做成单例就可以了。