Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference

Hello, I am practicing with the room database and it has been difficult for me to verify if a username and password exist in my database,the problem is that I am having problems with my application as it throws me the following error.(Attempt to invoke virtual method ‘android.content.Context android.content.Context.getApplicationContext()’ on a null object reference)

//User
@Entity(tableName = "user_table")
data class User(
        @PrimaryKey(autoGenerate = true)
        val id : Int ,
        val userName: String,
        val nameStudent: String,
        val grade: String,
        val password: String
)
//UserDao
@Dao
interface UserDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun addUser(user: User)

    @Query("SELECT * FROM user_table WHERE userName LIKE :name AND password LIKE:password")
    fun readAllData(name: String, password: String): List<User>

}

//UserDataBase
@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class UserDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

    companion object {
        @Volatile
        private var INSTANCE: UserDatabase? = null

        fun getDatabase(context: Context): UserDatabase{
            val tempInstance = INSTANCE
            if(tempInstance != null){
                return tempInstance
            }
            synchronized(this){
                val instance = Room.databaseBuilder(
                        context.applicationContext,
                        UserDatabase::class.java,
                        "user_database"
                ).build()
                INSTANCE = instance
                return instance
            }
        }

    }
}

//UserRepository
class UserRepository(private val userDao: UserDao, name:String,passWord:String ) {

    val readAllData: List<User> = userDao.readAllData(name,passWord)

    suspend fun adduser(user: User) {
        userDao.addUser(user)
    }

}

//UserViewModel
class UserViewModel(application: Application,name:String,passWord:String) : AndroidViewModel(application) {

    val readAllData: List<User>
    private val repository: UserRepository

    init {
        val userDao = UserDatabase.getDatabase(
            application
        ).userDao()
        repository = UserRepository(userDao,name, passWord)
        readAllData = repository.readAllData
    }

    fun addUser(user: User) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.adduser(user)
        }
    }

}
//UserViewModelFactory
class MyViewModelFactory(private var application: Application, private var name: String, private var passWord: String) :
    ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
            return UserViewModel(application, name, passWord) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

//mainFragment
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        super.onViewCreated(view, savedInstanceState)
        binding = FragmentMainBinding.bind(view)

        val name = binding.textInputUser.editText?.text.toString()
        val passWord = binding.textInputPassword.editText?.text.toString()

        val factory = activity?.application?.let { MyViewModelFactory(it,name, passWord) }
        mUserViewModel = factory?.let { ViewModelProvider(this, it).get(UserViewModel::class.java) }!!


        val x = context?.let { UserDatabase.getDatabase(it).userDao() }

        val y = x?.readAllData(name,passWord)

        binding.buttonIngresar.setOnClickListener {

            if (y != null) {
                findNavController().navigate(R.id.action_mainFragment_to_candidatesFragment)

            } else {
                Toast.makeText(context, "Usuario o contraseña no existe", Toast.LENGTH_SHORT).show()
            }

        }

    }

It’s because in MainFragment, you’re passing in a brand new Application class to your factory. Instead, replace this line:

val factory = MyViewModelFactory(Application(),"","")

With this:

val factory = MyViewModelFactory(activity?.application,"","")

Also as a tip make sure that you surround all code block with triple backticks like this:
```
// Code goes here
```
Which shows up like this:

// Code goes here

I have carried out your advice but I get this error

Type mismatch.
Required:
Application
Found:
Application?

//To solve the problem I do the following:
 val factory = activity? .application? .let {MyViewModelFactory (it, name, passWord)}
        mUserViewModel = factory? .let {ViewModelProvider (this, it) .get (UserViewModel :: class.java)} !!

but in the logcat, the following error is reflected. (Cannot access database on the main thread since it may potentially lock the UI for a long period of time.)

1 Like

You could probably do activity!!.application!! to solve that error too, but it shouldn’t matter.
That database error is then because of something else. Most likely, the error is in the readAllData method being not suspend, so you should mark it as suspend and then in your repository turn readAllData into a suspend fun instead, this means that you’ll then need to change the val readAllData to a lateinit var readAllData inside of the UserViewModel by changing this line in the UserViewModel init code:

readAllData = repository.readAllData

to this

viewModelScope.launch {
    readAllData = repository.readAllData()
}

and that should be it

Hello, I have followed your suggestions and for days I have tried to solve this problem and I have not been able to, my code:

//UserDao
@Dao
interface UserDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun addUser(user: User)

    @Query("SELECT * FROM user_table WHERE userName LIKE :name AND password LIKE:password")
    suspend fun readAllData(name: String, password: String): List<User>

}

//UserRepository
 class UserRepository(private val userDao: UserDao, val name: String, val passWord: String) {

    suspend fun readAllData(): List<User> = userDao.readAllData(name, passWord)

    suspend fun adduser(user: User) {
        userDao.addUser(user)
    }

}

//UserViewModel
class UserViewModel(application: Application,name:String,passWord:String) : AndroidViewModel(application) {

    lateinit var readAllData: List<User>
    private val repository: UserRepository

    init {
        val userDao = UserDatabase.getDatabase(
            application
        ).userDao()
        repository = UserRepository(userDao,name, passWord)
        viewModelScope.launch {
            readAllData = repository.readAllData()
        }
    }

    fun addUser(user: User) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.adduser(user)
        }
    }

}

//mainFragment
 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        super.onViewCreated(view, savedInstanceState)
        binding = FragmentMainBinding.bind(view)

        val factory = activity?.application?.let { MyViewModelFactory(it, "", "") }
        mUserViewModel = factory?.let { ViewModelProvider(this, it).get(UserViewModel::class.java) }!!

        val passWord = binding.textInputPassword.editText?.text.toString()
        val name = binding.textInputUser.editText?.text.toString()

        val x = context?.let { UserDatabase.getDatabase(it).userDao() }

//error in readAllData(Suspend function 'readAllData' should be called only from a coroutine or another suspend function)
        val y = x?.readAllData(name, passWord)

        binding.buttonIngresar.setOnClickListener {

            if (y != null) {
                findNavController().navigate(R.id.action_mainFragment_to_candidatesFragment)

            } else {
                Toast.makeText(context, "User or PassWord does not exist", Toast.LENGTH_SHORT).show()
            }

        }

    }

i have the same problem are you solve it??

You just need to start another thread or use Courtine (optional)
To start thread write

Thread{
val factory = activity? .application? .let {MyViewModelFactory (it, name, passWord)}
        mUserViewModel = factory? .let {ViewModelProvider (this, it) .get (UserViewModel :: class.java)} !!
}

The thread will finish as all the commands in it are completed