您的位置:首页 > 移动开发 > Android开发

【总结】Android开发中遇到的各种坑

2015-10-12 00:27 387 查看

前言

最近在弄一个小项目练练手,本来想着还是很简单的,结果一路碰壁,觉得一定要记下来,免得以后再被坑。(持续更新)

StackOverflow果然是一个神奇的网站,很多坑都可以在上面找到解决方案,当然,前提是要看得懂English,其实主要是会看代码即可,呵呵。

AlertDialog

我想点击按钮不关闭对话框

情景:

弹出一个对话框,用于输入密码,当点击按钮后,对密码进行校验,通过校验则关闭对话框,并继续后面的操作,当密码没通过校验时,只提示信息,不关闭对话框。

这是一个比较常用的情景(个人认为 - -),但是Google并没有提供相关的API来让开发者控制什么时候关闭对话框,而且API里面已经把这个写死了(Google这么设计肯定也有道理的,毕竟提示框的功能本来就是提示而已),不管点击的是哪个按钮(positive / neutral / negative),最终都会调用
dismiss()
来关闭
AlertDialog


这是
OnClickListener
的定义:

private final View.OnClickListener mButtonHandler = new View.OnClickListener() {
@Override
public void onClick(View v) {
final Message m;
if (v == mButtonPositive && mButtonPositiveMessage != null) {
m = Message.obtain(mButtonPositiveMessage);
} else if (v == mButtonNegative && mButtonNegativeMessage != null) {
m = Message.obtain(mButtonNegativeMessage);
} else if (v == mButtonNeutral && mButtonNeutralMessage != null) {
m = Message.obtain(mButtonNeutralMessage);
} else {
m = null;
}

if (m != null) {
m.sendToTarget();
}

// Post a message so we dismiss after the above handlers are executed
mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialog)
.sendToTarget();
}
};


再看看这个Handler如何处理这个Message:

public void handleMessage(Message msg) {
switch (msg.what) {

case DialogInterface.BUTTON_POSITIVE:
case DialogInterface.BUTTON_NEGATIVE:
case DialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
break;

case MSG_DISMISS_DIALOG:
((DialogInterface) msg.obj).dismiss(); // <<- 看这里
}
}


由此可见(注释已经写得很清楚了),在点击按钮后,
AlertDialog
肯定会被关闭的。

既然看清内幕了,那么解决方案是什么呢?

重写
Button
OnClickListener
How to prevent a dialog from closing when a button is clicked

注意: getButton 必须在 create 或者 show 之后调用,否则抛出NullPointerException

反射。(这是一个几乎可以解决任何问题大招)

通过反射,有好几种方法可以解决
AlertDialog
的关闭问题。其中比较最简单的一种方法,就是修改
Dialog
类中的
mShowing
字段的值(这个对话框根本没显示呀,不需要dismiss了)。

定义一个设置mShowing的方法:

public void canCloseDialog(DialogInterface dialog, boolean close)
try {
Field field = dialog.getClass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
field.set(dialog, close);
} catch (Exception e) {
e.printStackTrace();
}


然后这样使用就可以了:

new AlertDialog.Builder(this)
.setTitle("输入密码")
.setView(passwdEditText)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
canCloseDialog(dialogInterface, false); // false表示不关闭
}
})
.setNeutralButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

canCloseDialog(dialogInterface, true); // true表示会被关闭
}
})
.show();


本节到此结束,关于反射的其他方案就不说了,反正很少用到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: