Home > front end >  findViewById(R.id.editTextDialog) must not be null with custom dialog and ROOM database
findViewById(R.id.editTextDialog) must not be null with custom dialog and ROOM database

Time:10-24

I'm trying to implement adding an item to database, which is a string from editText dialog. Everything is all right, except when I press the "ok" button in the dialog everything crashes. I can't really figure out how to initiate the editText in this dialog with the insertDataToDatabase function

It gives me this error:

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>

CodePudding user response:

at insertDataToDatabase add a arg of type DialogInterface then cast it to AlertDialog

    private fun insertDataToDatabase(dialog: DialogInterface) {
        val editText = (dialog as AlertDialog).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()
        }
    }

and at showAddDialog to make it clear change _ on setPositiveButton to dialogInterface , and passe it to insertDataToDatabase

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