Issue
when the app is ran the following error occurs:
2022-08-03 15:41:29.243 21219-21250/com.example.roomdatabasetest E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.example.roomdatabasetest, PID: 21219
kotlin.UninitializedPropertyAccessException: **lateinit property userDB has not been initialized**
at com.example.roomdatabasetest.MainActivity$writeData$1.invokeSuspend(MainActivity.kt:52)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Basically I need to know how to initialise the User DB
If you require anymore code then please ask and any help is greatly appreciated.
Main Activity
package com.example.roomdatabasetest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import com.example.roomdatabasetest.data.User
import com.example.roomdatabasetest.data.UserDatabase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var btnWriteData: Button
private lateinit var btnReadData: Button
private lateinit var etFirstName: EditText
private lateinit var etLastName: EditText
private lateinit var userDB : UserDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnWriteData = findViewById(R.id.btnWriteData)
btnReadData = findViewById(R.id.btnReadData)
etFirstName = findViewById(R.id.etFirstName)
etLastName = findViewById(R.id.etLastName)
btnWriteData.setOnClickListener{
writeData()
}
btnReadData.setOnClickListener{
readData()
}
}
private fun writeData() {
val firstName = etFirstName.text.toString()
val lastName = etLastName.text.toString()
if(firstName.isNotEmpty() && lastName.isNotEmpty()) {
val user = User(
null, firstName, lastName
)
GlobalScope.launch(Dispatchers.IO){
userDB.userDao().insertAll(user)
}
etFirstName.text.clear()
etLastName.text.clear()
Toast.makeText(this, "Data Written", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(this, "Could Not Write Data", Toast.LENGTH_SHORT).show()
}
}
private fun readData(){
}
}
Solution
As the message says, you are not initialising the UserDb.
Either you need to use something along the lines of:-
User db = Room.databaseBuilder(this,UserDatabase::class.java,"the_database_name).allowMainThreadQueries().build()
- in both case initialising userDb would probably be done as part of the onCreate function (probably straight after retrieving the View id's)
Or if you use a singleton approach, which returns an instance of UserDatabase, which would require the context to be passsed to it and assuming the function, within the/a companion object is getInstance then
UserDb = UserData.getInstance(this)
Here's an example of a singleton approach but this would have to be modified to suit.
@Database(....) /* .... WILL HAVE TO BE CHANGED */
abstract class UserDatabase: RoomDatabase() {
abstract fun userDao: UserDao
companion object {
@Volatile
private var instance: UserDatabase?=null
fun getInstance(context: Context): UserDatabase {
if (instance==null) {
instance = Room.databaseBuilder(context,UserDatabase::class.java,"the_name_of_the_user_database")
.allowMainThreadQueries() /* as you are accessing the database on the main thread this will be required */
.build()
}
return instance as UserDatabase
}
}
}
- note that it is not recommended to access the database on the main thread, but you can.
Answered By - MikeT
Answer Checked By - Cary Denson (JavaFixing Admin)