I've been following an Android App Development tutorial on Udemy and was working on getting the room database working.
Link to the GitHub: https://github.com/tutorialseu/RoomDatabaseDemo/tree/169_completing_the_demo
For some reason, the following line causes the app to crash once loaded. I have tried to follow the tutorial as closely as I can and even copied some parts of the code, and yet nothing seems to work.
val employeeDao = (application as EmployeeApp).db.employeeDao()
Below are the rest of the codes:
(Main Activity)
package com.example.roomdatabasedemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.example.roomdatabasedemo.databinding.ActivityMainBinding
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
val employeeDao = (application as EmployeeApp).db.employeeDao()
binding?.btnAdd?.setOnClickListener {
addRecord(employeeDao)
}
}
private fun addRecord(employeeDao: EmployeeDao) {
val name = binding?.etName?.text.toString()
val email = binding?.etEmailId?.text.toString()
if (name.isNotEmpty() && email.isNotEmpty()) {
lifecycleScope.launch {
employeeDao.insert(EmployeeEntity(name = name, email = email))
Toast.makeText(
applicationContext,
"Record saved.",
Toast.LENGTH_SHORT
).show()
binding?.etName?.text?.clear()
binding?.etEmailId?.text?.clear()
}
}
else {
Toast.makeText(
applicationContext,
"Name or Email cannot be blank.",
Toast.LENGTH_SHORT
).show()
}
}
}
(Database)
package com.example.roomdatabasedemo
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [EmployeeEntity::class], version = 2)
abstract class EmployeeDatabase: RoomDatabase() {
abstract fun employeeDao(): EmployeeDao
companion object {
@Volatile
private var INSTANCE: EmployeeDatabase? = null
fun getInstance(context: Context): EmployeeDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
EmployeeDatabase::class.java,
"employee_database"
).fallbackToDestructiveMigration().build()
INSTANCE = instance
}
return instance
}
}
}
}
(Dao)
package com.example.roomdatabasedemo
import androidx.room.*
import kotlinx.coroutines.flow.Flow
@Dao
interface EmployeeDao {
@Insert
suspend fun insert(employeeEntity: EmployeeEntity)
@Update
suspend fun update(employeeEntity: EmployeeEntity)
@Delete
suspend fun delete(employeeEntity: EmployeeEntity)
@Query("SELECT * FROM `employee-table`")
fun fetchAllEmployees(): Flow<List<EmployeeEntity>>
@Query("SELECT * FROM `employee-table` where id=:id")
fun fetchEmployeebyId(id: Int): Flow<List<EmployeeEntity>>
}
(Entity)
package com.example.roomdatabasedemo
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "employee-table")
data class EmployeeEntity(
@PrimaryKey(autoGenerate = true)
var id: Int=0,
var name: String="",
@ColumnInfo(name = "email-id")
var email: String=""
)
(App)
package com.example.roomdatabasedemo
import android.app.Application
class EmployeeApp: Application() {
val db by lazy {
EmployeeDatabase.getInstance(this)
}
}
(Android Manifest)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.roomdatabasedemo">
<application
android:allowBackup="true"
android:name=".EmployeeApp"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RoomDatabaseDemo"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
(gradle:app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.roomdatabasedemo"
minSdk 24
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.room:room-runtime:2.4.2'
annotationProcessor 'androidx.room:room-compiler:2.4.2'
implementation('androidx.room:room-ktx:2.4.2')
implementation 'androidx.activity:activity-ktx:1.5.0'
implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
(gradle: module)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.2.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Below is the error message I got when I tried to debug it.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.roomdatabasedemo, PID: 30895
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roomdatabasedemo/com.example.roomdatabasedemo.MainActivity}: java.lang.RuntimeException: cannot find implementation for com.example.roomdatabasedemo.EmployeeDatabase. EmployeeDatabase_Impl does not exist
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4035)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4201)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2438)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Caused by: java.lang.RuntimeException: cannot find implementation for com.example.roomdatabasedemo.EmployeeDatabase. EmployeeDatabase_Impl does not exist
at androidx.room.Room.getGeneratedImplementation(Room.java:100)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1486)
at com.example.roomdatabasedemo.EmployeeDatabase$Companion.getInstance(EmployeeDatabase.kt:26)
at com.example.roomdatabasedemo.EmployeeApp$db$2.invoke(EmployeeApp.kt:7)
at com.example.roomdatabasedemo.EmployeeApp$db$2.invoke(EmployeeApp.kt:6)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.example.roomdatabasedemo.EmployeeApp.getDb(EmployeeApp.kt:6)
at com.example.roomdatabasedemo.MainActivity.onCreate(MainActivity.kt:19)
at android.app.Activity.performCreate(Activity.java:8290)
at android.app.Activity.performCreate(Activity.java:8270)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4009)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4201)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2438)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Please help me with what went wrong with line "val employeeDao = (application as EmployeeApp).db.employeeDao()". Sorry for making the question vague. I am very inexperienced in this field and have no idea how to specify the issue further.
Any help will be appreciated.
CodePudding user response:
Use these implementations for room
implementation 'androidx.room:room-runtime:2.4.2'
kapt 'androidx.room:room-compiler:2.4.2'
implementation 'androidx.room:room-ktx:2.4.2'
Put these in your app/build.gradle
CodePudding user response:
Looks like I have messed up in the Gradle file. I had to use version 1.5 of the following dependency (and not above) for the app to work.
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.32"