You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Dialog结合ROOM数据库时EditText空指针异常求助

问题描述

我正尝试实现从自定义Dialog的EditText中获取字符串并添加到ROOM数据库的功能,其余功能均正常,但点击Dialog的“ok”按钮时程序崩溃。我无法明确如何在insertDataToDatabase函数中正确初始化Dialog内的EditText。

报错信息

java.lang.NullPointerException: Attempt to invoke virtual method
android.text.Editable android.widget.EditText.getText() on a null
object reference at
com.example.planner3.MainActivity.insertDataToDatabase(MainActivity.kt:75)
at
com.example.planner3.MainActivity.showAddDialog$lambda-2(MainActivity.kt:100)

相关代码

MainActivity.kt

package com.example.planner3

import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import android.view.Menu
import android.view.MenuItem
import android.widget.EditText
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.example.planner3.databinding.ActivityMainBinding
import com.example.planner3.model.User
import com.example.planner3.viewmodel.UserViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding
    private lateinit var mUserViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {

        WindowCompat.setDecorFitsSystemWindows(window, false)
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        mUserViewModel = ViewModelProvider(this)[UserViewModel::class.java]
        setSupportActionBar(binding.toolbar)

        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)
        supportActionBar!!.setBackgroundDrawable(ColorDrawable(Color.parseColor("#59da66")))


        binding.floatingActionButton.setOnClickListener {
            //navController.navigate(R.id.action_RecyclerFragment_to_AddFragment)
            showAddDialog()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        return when (item.itemId) {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        return navController.navigateUp(appBarConfiguration)
                || super.onSupportNavigateUp()
    }

    private fun insertDataToDatabase() {
        val editText = findViewById<EditText>(R.id.editTextDialog)
        val task = editText.text.toString()

        if(inputCheck(task)) {
            // Create an entity
            val user = User(0, task)
            mUserViewModel.addUser(user)
            Toast.makeText(this, "Task added", Toast.LENGTH_SHORT).show()
        }
        else {
            Toast.makeText(this, "Please fill out required fields", Toast.LENGTH_SHORT).show()
        }
    }

    private fun inputCheck(task: String): Boolean {
        return !(TextUtils.isEmpty(task))
    }

    private fun showAddDialog() {
        MaterialAlertDialogBuilder(this)
            .setView(R.layout.fragment_add)
            .setNegativeButton("cancel") { _, _ ->
                // Respond to negative button press
            }
            .setPositiveButton("ok") { _, _ ->
                // Respond to positive button press
                insertDataToDatabase()
            }
            .show()
    }
}

fragment_add.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="15dp"
        tools:ignore="UselessParent">

        <EditText
            android:id="@+id/editTextDialog"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="15dp"
            android:gravity="center"
            android:hint="Hint"
            android:paddingTop="15dp"
            android:textColorHint="#757575"
            tools:ignore="Autofill,TextFields" />
    </LinearLayout>
</LinearLayout>
解决方案

崩溃的核心原因是:你调用findViewById<EditText>(R.id.editTextDialog)时,是从Activity的视图层级中查找控件,但这个EditText属于Dialog的独立布局,不在Activity的视图树里,所以返回null,后续调用getText()就触发了空指针异常。

修改步骤如下:

  1. 在showAddDialog方法中,先手动inflate出Dialog的布局,获取到EditText的引用。
  2. 点击ok按钮时,直接用这个引用获取输入内容,再传递给插入数据库的方法。

修改后的代码片段:

// 修改insertDataToDatabase方法,接收传入的task参数
private fun insertDataToDatabase(task: String) {
    if(inputCheck(task)) {
        val user = User(0, task)
        mUserViewModel.addUser(user)
        Toast.makeText(this, "Task added", Toast.LENGTH_SHORT).show()
    }
    else {
        Toast.makeText(this, "Please fill out required fields", Toast.LENGTH_SHORT).show()
    }
}

private fun showAddDialog() {
    // 先加载Dialog的布局,获取到EditText引用
    val dialogView = layoutInflater.inflate(R.layout.fragment_add, null)
    val editText = dialogView.findViewById<EditText>(R.id.editTextDialog)
    
    MaterialAlertDialogBuilder(this)
        .setView(dialogView) // 设置加载好的布局
        .setNegativeButton("cancel") { _, _ -> }
        .setPositiveButton("ok") { _, _ ->
            val task = editText.text.toString()
            insertDataToDatabase(task) // 把输入内容传进去
        }
        .show()
}

这样修改后,就能正确获取到Dialog内EditText的引用,避免空指针问题,同时逻辑也更清晰。

内容的提问来源于stack exchange,提问作者Juncu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:10:36