Android Kotlin findViewById 不能为空
Android Kotlin findViewById must not be null
我们通过将其转换为 Kotlin 创建了一个在 Java 项目中使用的自定义警报对话框下面发布的错误
java.lang.IllegalStateException: findViewById(R.id.btnYES) 不能为空
错误来源在躲避我们!我们查看了许多帖子并尝试了一些但没有结果。 Activity 结构如下 PageTwoActivity 有自己的 XML 文件,附有两个按钮。自定义对话框有自己的 xml 文件
这是 PageTwoActivity 代码。没有 PageTwoActivity 的两个按钮
没有名称冲突
import android.app.Dialog
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
class PageTwoActivity : AppCompatActivity() {
internal lateinit var btnBACK: Button
internal lateinit var btnDIALOG: Button
internal lateinit var btnYES: Button
internal lateinit var btnNO: Button
internal lateinit var etStudentName:EditText
var EnteredText: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_page_two)
btnBACK = findViewById(R.id.btnBACK)
btnDIALOG = findViewById(R.id.btnDIALOG)
btnYES = findViewById(R.id.btnYES)
btnNO = findViewById(R.id.btnNO)
etStudentName = findViewById(R.id.etStudentName)
addListenerOnButtonBACK()
addListenerOnButtonDIALOG()
Toast.makeText(this@PageTwoActivity, "You are on Page Two",
Toast.LENGTH_LONG).show()
}// END onCreate
这是自定义对话框的代码
private fun doCustom() {
val openDialog = Dialog(this)
openDialog.setContentView(R.layout.custom_dialog)
//val btnYES = view!!.findViewById<Button>(R.id.btnYES)
//val btnNO = openDialog.findViewById(R.id.btnNO)
//val etStudentName = openDialog.findViewById(R.id.etStudentName)
openDialog.setCancelable(false)
btnYES.setOnClickListener(View.OnClickListener {
EnteredText = etStudentName.getText().toString().trim({ it <= ' ' })
if (EnteredText.isEmpty()) {
Toast.makeText(applicationContext, "Enter Your Name\n\n OR Click
DECLINE", Toast.LENGTH_LONG).show()
return@OnClickListener
}
Toast.makeText(applicationContext, "Registered $EnteredText",
Toast.LENGTH_SHORT).show()
openDialog.dismiss()
})
btnNO.setOnClickListener(View.OnClickListener {
EnteredText = ""
val intent = Intent(this@PageTwoActivity, MainActivity::class.java)
startActivity(intent)
openDialog.dismiss()
})
openDialog.show()
}
自定义对话框的 XML 文件代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="400dp"
android:layout_height="200dp"
android:background="@color/color_lightGray">
<TextView
android:id="@+id/tvDAT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="70dp"
android:layout_marginTop="30dp"
android:text="Enter First and Last Name"
android:textColor="@color/color_Black"
android:textSize="22sp"
android:textStyle="bold" />
<EditText
android:id="@+id/etStudentName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="80dp"
android:ems="14"
android:gravity="center"
android:inputType="textPersonName"
android:text=""
android:textColor="@color/color_Black"
android:textSize="20sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnYES"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="250dp"
android:layout_marginTop="120dp"
android:background="@color/color_Transparent"
android:text="TAKE QUIZ"
android:textColor="@color/color_deepBlue"
android:textSize="22sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnNO"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="22dp"
android:layout_marginTop="120dp"
android:background="@color/color_Transparent"
android:text="DECLINE"
android:textColor="@color/color_deepBlue"
android:textSize="22sp"
android:textStyle="bold" />
</RelativeLayout>
所以问题是我们如何修复错误?
我们应该扩充自定义对话框 xml 吗?
如您所见,我们试图将用于查找 id 的声明移动到 doCustom 函数中 //val btnYES = view!!.findViewById(R.id.btnYES)
这个 link 提供了建议,但我们不知道从哪里开始
LINK
findViewByID()
returns 一个可为 null 的对象。
btnYES = findViewById(R.id.btnYES)
尝试将可为 null 的视图分配给 lateinit 不可为 null 的视图。
这就是解决方案。
将此 internal lateinit var btnYES: Button
更改为此 internal lateinit var btnYES: Button?
或
将此 btnYES = findViewById(R.id.btnYES)
更改为此 btnYES = findViewById(R.id.btnYES)!!
您可以采用一种方法,而不是尝试使用 setContentView 自定义对话框,您可以使用新的自定义对话框片段扩展 DialogFragment。然后你可以像处理片段一样处理它;您在 onCreateDialog 中膨胀视图,这是我在类似问题中找到的一种方法:
public class PopupAlert extends DialogFragment {
TextView heading;
TextView popupMessage;
Button okBtn;
private Runnable onDismissRunnable;
private String titleText;
private String messageText;
private View.OnClickListener positiveListener;
public void setOnDismissRunnable(Runnable runnable) {
this.onDismissRunnable = runnable;
}
public void setOkBtnText(String text) {
this.okBtnText = text;
}
public static PopupAlert newInstance(String title, String message) {
PopupAlert alert = new PopupAlert();
alert.titleText = title;
alert.messageText = message;
return alert;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissRunnable != null) onDismissRunnable.run();
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
@SuppressLint("InflateParams") View view = LayoutInflater.from(getContext()).inflate(R.layout.view_popup_alert, null);
fetchViews(view);
builder.setView(view);
return builder.create();
}
private void fetchViews(View view) {
heading = view.findViewById(R.id.popupHeading);
popupMessage = view.findViewById(R.id.popupMessage);
okBtn = view.findViewById(R.id.okBtn);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bindToData();
}
private void bindToData() {
heading.setText(titleText);
popupMessage.setText(messageText);
okBtn.setOnClickListener((v) -> dismiss());
okBtn.setText(okBtnText);
}
}
正如@Declan Nnadozie 已经提到的那样:btnYES = findViewById(R.id.btnYES)
returns null
因为 btnYES
不是 contentView
内的视图膨胀到 PageTwoActivity
.
按钮 btnYES
和 btnNO
以及 EditText etStudentName
可以在对话框中膨胀的内容中找到:
同样在 Kotlin 中,您不需要 findViewById 来访问 activity 的视图。
您可以删除所有这些:
internal lateinit var btnBACK: Button
internal lateinit var btnDIALOG: Button
internal lateinit var btnYES: Button
internal lateinit var btnNO: Button
internal lateinit var etStudentName:EditText
我的建议是使用下面的代码:
class PageTwoActivity : AppCompatActivity() {
var EnteredText: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_page_two)
addListenerOnButtonBACK()
addListenerOnButtonDIALOG()
Toast.makeText(this@PageTwoActivity, "You are on Page Two",
Toast.LENGTH_LONG).show()
}
fun doCustom(v: View) {
val openDialog = Dialog(this)
openDialog.setContentView(R.layout.custom_dialog)
val btnYES = openDialog.findViewById<Button>(R.id.btnYES)
val btnNO = openDialog.findViewById<Button>(R.id.btnNO)
val etStudentName = openDialog.findViewById<EditText>(R.id.etStudentName)
openDialog.setCancelable(false)
btnYES.setOnClickListener(View.OnClickListener {
EnteredText = etStudentName.getText().toString().trim({ it <= ' ' })
if (EnteredText.isEmpty()) {
Toast.makeText(applicationContext, "Enter Your Name\n\n OR Click DECLINE", Toast.LENGTH_LONG).show()
return@OnClickListener
}
Toast.makeText(applicationContext, "Registered $EnteredText", Toast.LENGTH_SHORT).show()
openDialog.dismiss()
})
btnNO.setOnClickListener(View.OnClickListener {
EnteredText = ""
val intent = Intent(this@PageTwoActivity, MainActivity::class.java)
startActivity(intent)
openDialog.dismiss()
})
openDialog.show()
}
我遇到了同样的问题。我解决了将 findViewById 放入 customAlertButton.setOnClickListener:
customAlertButton.setOnClickListener {
val customDialog = Dialog(this)
customDialog.setContentView(R.layout.custom_alert_layout)
customDialog.show()
val button1 = customDialog.findViewById<View>(R.id.button1)
val button2 = customDialog.findViewById<View>(R.id.button2)
val button3 = customDialog.findViewById<View>(R.id.button3)
button1.setOnClickListener {
Toast.makeText(this, "Called by button1", Toast.LENGTH_SHORT).show()
}
button2.setOnClickListener {
Toast.makeText(this, "Called by button2", Toast.LENGTH_SHORT).show()
}
button3.setOnClickListener {
Toast.makeText(this, "Called by button3", Toast.LENGTH_SHORT).show()
}
}
我们通过将其转换为 Kotlin 创建了一个在 Java 项目中使用的自定义警报对话框下面发布的错误 java.lang.IllegalStateException: findViewById(R.id.btnYES) 不能为空
错误来源在躲避我们!我们查看了许多帖子并尝试了一些但没有结果。 Activity 结构如下 PageTwoActivity 有自己的 XML 文件,附有两个按钮。自定义对话框有自己的 xml 文件 这是 PageTwoActivity 代码。没有 PageTwoActivity 的两个按钮 没有名称冲突
import android.app.Dialog
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
class PageTwoActivity : AppCompatActivity() {
internal lateinit var btnBACK: Button
internal lateinit var btnDIALOG: Button
internal lateinit var btnYES: Button
internal lateinit var btnNO: Button
internal lateinit var etStudentName:EditText
var EnteredText: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_page_two)
btnBACK = findViewById(R.id.btnBACK)
btnDIALOG = findViewById(R.id.btnDIALOG)
btnYES = findViewById(R.id.btnYES)
btnNO = findViewById(R.id.btnNO)
etStudentName = findViewById(R.id.etStudentName)
addListenerOnButtonBACK()
addListenerOnButtonDIALOG()
Toast.makeText(this@PageTwoActivity, "You are on Page Two",
Toast.LENGTH_LONG).show()
}// END onCreate
这是自定义对话框的代码
private fun doCustom() {
val openDialog = Dialog(this)
openDialog.setContentView(R.layout.custom_dialog)
//val btnYES = view!!.findViewById<Button>(R.id.btnYES)
//val btnNO = openDialog.findViewById(R.id.btnNO)
//val etStudentName = openDialog.findViewById(R.id.etStudentName)
openDialog.setCancelable(false)
btnYES.setOnClickListener(View.OnClickListener {
EnteredText = etStudentName.getText().toString().trim({ it <= ' ' })
if (EnteredText.isEmpty()) {
Toast.makeText(applicationContext, "Enter Your Name\n\n OR Click
DECLINE", Toast.LENGTH_LONG).show()
return@OnClickListener
}
Toast.makeText(applicationContext, "Registered $EnteredText",
Toast.LENGTH_SHORT).show()
openDialog.dismiss()
})
btnNO.setOnClickListener(View.OnClickListener {
EnteredText = ""
val intent = Intent(this@PageTwoActivity, MainActivity::class.java)
startActivity(intent)
openDialog.dismiss()
})
openDialog.show()
}
自定义对话框的 XML 文件代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="400dp"
android:layout_height="200dp"
android:background="@color/color_lightGray">
<TextView
android:id="@+id/tvDAT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="70dp"
android:layout_marginTop="30dp"
android:text="Enter First and Last Name"
android:textColor="@color/color_Black"
android:textSize="22sp"
android:textStyle="bold" />
<EditText
android:id="@+id/etStudentName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="80dp"
android:ems="14"
android:gravity="center"
android:inputType="textPersonName"
android:text=""
android:textColor="@color/color_Black"
android:textSize="20sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnYES"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="250dp"
android:layout_marginTop="120dp"
android:background="@color/color_Transparent"
android:text="TAKE QUIZ"
android:textColor="@color/color_deepBlue"
android:textSize="22sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnNO"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="22dp"
android:layout_marginTop="120dp"
android:background="@color/color_Transparent"
android:text="DECLINE"
android:textColor="@color/color_deepBlue"
android:textSize="22sp"
android:textStyle="bold" />
</RelativeLayout>
所以问题是我们如何修复错误? 我们应该扩充自定义对话框 xml 吗? 如您所见,我们试图将用于查找 id 的声明移动到 doCustom 函数中 //val btnYES = view!!.findViewById(R.id.btnYES) 这个 link 提供了建议,但我们不知道从哪里开始 LINK
findViewByID()
returns 一个可为 null 的对象。
btnYES = findViewById(R.id.btnYES)
尝试将可为 null 的视图分配给 lateinit 不可为 null 的视图。
这就是解决方案。
将此 internal lateinit var btnYES: Button
更改为此 internal lateinit var btnYES: Button?
或
将此 btnYES = findViewById(R.id.btnYES)
更改为此 btnYES = findViewById(R.id.btnYES)!!
您可以采用一种方法,而不是尝试使用 setContentView 自定义对话框,您可以使用新的自定义对话框片段扩展 DialogFragment。然后你可以像处理片段一样处理它;您在 onCreateDialog 中膨胀视图,这是我在类似问题中找到的一种方法:
public class PopupAlert extends DialogFragment {
TextView heading;
TextView popupMessage;
Button okBtn;
private Runnable onDismissRunnable;
private String titleText;
private String messageText;
private View.OnClickListener positiveListener;
public void setOnDismissRunnable(Runnable runnable) {
this.onDismissRunnable = runnable;
}
public void setOkBtnText(String text) {
this.okBtnText = text;
}
public static PopupAlert newInstance(String title, String message) {
PopupAlert alert = new PopupAlert();
alert.titleText = title;
alert.messageText = message;
return alert;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissRunnable != null) onDismissRunnable.run();
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
@SuppressLint("InflateParams") View view = LayoutInflater.from(getContext()).inflate(R.layout.view_popup_alert, null);
fetchViews(view);
builder.setView(view);
return builder.create();
}
private void fetchViews(View view) {
heading = view.findViewById(R.id.popupHeading);
popupMessage = view.findViewById(R.id.popupMessage);
okBtn = view.findViewById(R.id.okBtn);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bindToData();
}
private void bindToData() {
heading.setText(titleText);
popupMessage.setText(messageText);
okBtn.setOnClickListener((v) -> dismiss());
okBtn.setText(okBtnText);
}
}
正如@Declan Nnadozie 已经提到的那样:btnYES = findViewById(R.id.btnYES)
returns null
因为 btnYES
不是 contentView
内的视图膨胀到 PageTwoActivity
.
按钮 btnYES
和 btnNO
以及 EditText etStudentName
可以在对话框中膨胀的内容中找到:
同样在 Kotlin 中,您不需要 findViewById 来访问 activity 的视图。
您可以删除所有这些:
internal lateinit var btnBACK: Button
internal lateinit var btnDIALOG: Button
internal lateinit var btnYES: Button
internal lateinit var btnNO: Button
internal lateinit var etStudentName:EditText
我的建议是使用下面的代码:
class PageTwoActivity : AppCompatActivity() {
var EnteredText: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_page_two)
addListenerOnButtonBACK()
addListenerOnButtonDIALOG()
Toast.makeText(this@PageTwoActivity, "You are on Page Two",
Toast.LENGTH_LONG).show()
}
fun doCustom(v: View) {
val openDialog = Dialog(this)
openDialog.setContentView(R.layout.custom_dialog)
val btnYES = openDialog.findViewById<Button>(R.id.btnYES)
val btnNO = openDialog.findViewById<Button>(R.id.btnNO)
val etStudentName = openDialog.findViewById<EditText>(R.id.etStudentName)
openDialog.setCancelable(false)
btnYES.setOnClickListener(View.OnClickListener {
EnteredText = etStudentName.getText().toString().trim({ it <= ' ' })
if (EnteredText.isEmpty()) {
Toast.makeText(applicationContext, "Enter Your Name\n\n OR Click DECLINE", Toast.LENGTH_LONG).show()
return@OnClickListener
}
Toast.makeText(applicationContext, "Registered $EnteredText", Toast.LENGTH_SHORT).show()
openDialog.dismiss()
})
btnNO.setOnClickListener(View.OnClickListener {
EnteredText = ""
val intent = Intent(this@PageTwoActivity, MainActivity::class.java)
startActivity(intent)
openDialog.dismiss()
})
openDialog.show()
}
我遇到了同样的问题。我解决了将 findViewById 放入 customAlertButton.setOnClickListener:
customAlertButton.setOnClickListener {
val customDialog = Dialog(this)
customDialog.setContentView(R.layout.custom_alert_layout)
customDialog.show()
val button1 = customDialog.findViewById<View>(R.id.button1)
val button2 = customDialog.findViewById<View>(R.id.button2)
val button3 = customDialog.findViewById<View>(R.id.button3)
button1.setOnClickListener {
Toast.makeText(this, "Called by button1", Toast.LENGTH_SHORT).show()
}
button2.setOnClickListener {
Toast.makeText(this, "Called by button2", Toast.LENGTH_SHORT).show()
}
button3.setOnClickListener {
Toast.makeText(this, "Called by button3", Toast.LENGTH_SHORT).show()
}
}