【问题标题】:Android Kotlin findViewById must not be nullAndroid Kotlin findViewById 不能为空
【发布时间】:2018-08-15 00:47:58
【问题描述】:

我们通过将其转换为 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

【问题讨论】:

  • 添加堆栈跟踪
  • 由于缺乏努力进行研究,问题被否决了这不是真的我们在每个地方都查看了一个又一个帖子,即使在 Stackoverflow 上我们测试了很多我们发现没有结果的代码我想添加如果没有至少 4 小时或 2 天的阅读和研究,我们不会提出问题

标签: android kotlin android-alertdialog


【解决方案1】:

正如@Declan Nnadozie 已经提到的那样:btnYES = findViewById(R.id.btnYES) 返回null,因为btnYES 不是contentView 内部的视图膨胀到PageTwoActivity
按钮 btnYESbtnNO 以及 EditText etStudentName 可以在对话框中的膨胀内容中找到:
同样在 Kotlin 中,您不需要 findViewById 来访问活动的视图。
您可以删除所有这些:

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()
    }

【讨论】:

    【解决方案2】:

    findViewByID() 返回一个可为空的对象。

    btnYES = findViewById(R.id.btnYES)
    

    尝试将可空视图分配给 lateinit 不可空视图。

    所以这是解决方案。 将此internal lateinit var btnYES: Button 更改为此internal lateinit var btnYES: Button?

    或者

    把这个btnYES = findViewById(R.id.btnYES)改成这个btnYES = findViewById(R.id.btnYES)!!

    【讨论】:

    • 感谢您的反馈,但需要与您分享这两个建议都会产生不允许使用的警告,因此语法结构无法使用
    【解决方案3】:

    您可以采取的一种方法是,您可以使用新的自定义对话框片段来扩展 DialogFragment,而不是尝试使用 setContentView 自定义对话框。然后你可以像处理片段一样处理它;您在 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-01
      • 2018-05-04
      • 2021-06-27
      • 2022-01-09
      相关资源
      最近更新 更多