尽管对话框具有正按钮,但AlertDialog.getButton(AlertDialog.BUTTON_POSITIVE)返回null

时间:2020-10-30 00:13:32

标签: android kotlin

我有一个扩展AppCompatDialogFragment的类。我希望它创建一个弹出窗口,用户可以在其中输入密码。但是每次运行该应用程序时,都会出现此错误。

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference

这是我的类onCreateDialog方法的代码:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    //The popup
    val mBuilder = AlertDialog.Builder(activity)
    val mFlater = activity?.layoutInflater
    val mView =mFlater?.inflate(R.layout.activity_get_password, null)

    //Get the EditText
    val getPassword: EditText = mView!!.findViewById(R.id.getPassword)

    mBuilder.setPositiveButton("Ok"){ _, _ ->}

    //Set the view
    mBuilder.setView(mView)

    //Set the AlertDialog
    val alertDialog = mBuilder.create().apply {
        setCanceledOnTouchOutside(false)
    }

    //Set the clicklistener for the
    alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
        val password = getPassword.text.toString()
        if(password == db?.getPassword()) {
            //Send the password
            interfaces?.getPassword(password)

            //Close the alert dialog
            alertDialog.dismiss()
        } else //Wrong password?
            Toast.makeText(context, "Invalid Password!", Toast.LENGTH_LONG).show()
    }

    return alertDialog
}

2 个答案:

答案 0 :(得分:0)

您必须在show()之前致电getButton()。如果要在显示对话框时自动设置ClickListener回调,请选中this answer


您需要了解platform type。在kotlin中调用java方法时,除非您使用@NotNull或@Nullable批注,否则它将返回平台类型。

例如,alertDialog.getButton()返回平台类型(空)。 无论返回值是null还是非null,Kotlin的行为都类似于非null,因为它是平台类型。 因此,即使返回null,也会调用null.setOnClickListener()

答案 1 :(得分:0)

根本原因:来自AlertDialog源代码:

/**
 * Gets one of the buttons used in the dialog. Returns null if the specified
 * button does not exist or the dialog has not yet been fully created (for
 * example, via {@link #show()} or {@link #create()}).
 *
 * @param whichButton The identifier of the button that should be returned.
 *                    For example, this can be
 *                    {@link DialogInterface#BUTTON_POSITIVE}.
 * @return The button from the dialog, or null if a button does not exist.
 */
public Button getButton(int whichButton) {
    return mAlert.getButton(whichButton);
}

在您的情况下,由于尚未通过show()create()完全创建对话框,因此getButton()方法返回null

解决方案::在调用getButton()方法以确保对话框已完全创建之前,先调用这两种方法。

// Set the AlertDialog
val alertDialog = mBuilder.create().apply {
    setCanceledOnTouchOutside(false)
}

// Calling show or create method here
alertDialog.show(); // or alertDialog.create();

// Set the clicklistener for the
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
    val password = getPassword.text.toString()
    if (password == db?.getPassword()) {
        //Send the password
        interfaces?.getPassword(password)

        //Close the alert dialog
        alertDialog.dismiss()
    } else { //Wrong password?
        Toast.makeText(context, "Invalid Password!", Toast.LENGTH_LONG).show()
    }
}