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

前言

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

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肯定会被关闭的。
既然看清内幕了,那么解决方案是什么呢?

  1. 重写ButtonOnClickListenerHow to prevent a dialog from closing when a button is clicked
    注意: getButton 必须在 create 或者 show 之后调用,否则抛出NullPointerException

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

通过反射,有好几种方法可以解决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();

本节到此结束,关于反射的其他方案就不说了,反正很少用到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值