I am implementing Room persistence lib in kotlin for my database implementation.
Same question is asked in Android Room Persistences library and Kotlin thread, applying those solution resulted in different gradle errors:
Following are my Entity, Dao and Database classes:
Food.kt
#Entity
class Food(#ColumnInfo(name = "food_name") var foodName: String,
#ColumnInfo(name = "food_desc") var foodDesc: String,
#ColumnInfo(name = "protein") var protein: Double,
#ColumnInfo(name = "carbs") var carbs: Double,
#ColumnInfo(name = "fat") var fat: Double)
{
#ColumnInfo(name = "id")
#PrimaryKey(autoGenerate = true)
var id: Long = 0
#ColumnInfo(name = "calories")
var calories: Double = 0.toDouble()
}
PersonalizedFood.kt
#Entity(primaryKeys = arrayOf("food_id","date"))
class PersonalizedFood(#ColumnInfo(name = "quantity") var quantity: Int,
#ColumnInfo(name = "unit") var unit: String,
#ColumnInfo(name = "date") var date: Date){
#ColumnInfo(name = "food_id")
var foodId:Long = 0
}
FoodDao.kt
#Dao
interface FoodDao {
companion object{
const val ID = "id"
const val NAME = "name"
const val PROTEIN = "protein"
const val DESC = "desc"
const val CARBS = "carbs"
const val FAT = "fat"
const val DATE = "date"
const val FOOD_ID = "food_id"
const val ALL_FOOD_LIST = "food"
const val PERSONALISED_FOOD_LIST = "personalised_food"
}
/**
* Returns food details of a food given by food_id
*/
#Query("SELECT * FROM $ALL_FOOD_LIST WHERE $ID=:food_id")
fun getFoodDetails(food_id:Long):Food
/**
* Inserts food items in all_food_list
*/
#Insert
fun addFoodList(list:ArrayList<Food>)
#Insert(onConflict = REPLACE)
fun saveFood(food:PersonalizedFood)
#Query("SELECT * FROM $PERSONALISED_FOOD_LIST WHERE $FOOD_ID=:foodId and $DATE=:date")
fun getFood(foodId:Int, data:Date):PersonalizedFood
#Query("SELECT * FROM $ALL_FOOD_LIST where $ID in (select $FOOD_ID from $PERSONALISED_FOOD_LIST where $DATE = :date)")
fun getFood(date:Date):ArrayList<Food>
}
Converter.kt
class Converter {
companion object{
#TypeConverter
fun fromTimestamp(value: Long?): Date? {
return if (value == null) null else Date(value)
}
#TypeConverter
fun dateToTimestamp(date: Date): Long {
return date.time
}
}
}
FoodDatabase.kt
#Database(entities = arrayOf(Food::class, PersonalizedFood::class), version = 1)
#TypeConverters(Converter::class)
abstract class FoodDatabase : RoomDatabase(){
abstract fun foodDao():FoodDao
companion object{
private val databaseName = "diet"
var dbInstance:FoodDao? = null
fun getInstance(context:Context):FoodDao?{
if(dbInstance == null)
dbInstance = Room.inMemoryDatabaseBuilder(context, FoodDatabase::class.java).build().foodDao()
return dbInstance;
}
}
}
And when i run following code to create database:
FoodDatabase.getInstance(baseContext)?.getFood(Calendar.getInstance().time)
It gives me following exception:
Caused by: java.lang.RuntimeException: cannot find implementation for com.chandilsachin.diettracker.database.FoodDatabase. FoodDatabase_Impl does not exist
at android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90)
at android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:340)
at com.chandilsachin.diettracker.database.FoodDatabase$Companion.getInstance(FoodDatabase.kt:21)
at com.chandilsachin.diettracker.MainActivity$SetUpFoodDatabase.doInBackground(MainActivity.kt:95)
at com.chandilsachin.diettracker.MainActivity$SetUpFoodDatabase.doInBackground(MainActivity.kt:77)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Has anyone implemented room persistence in kotlin?
Edited
My previous question on same topic was marked duplicate of this. Though problem statement is same but solution given does not solve my problem. Solution says i have to add replace annotationProcessor to kapt "android.arch.persistence.room:compiler:1.0.0-alpha1" dependency. I made those changes and it resulted in gradle error while project build.
Information:Gradle tasks [:app:assembleDebug]
Warning:warning: Supported source version 'RELEASE_7' from annotation processor 'android.arch.persistence.room.RoomProcessor' less than -source '1.8'
Warning:warning: The following options were not recognized by any processor: '[kapt.kotlin.generated]'
/Users/BBI-M1025/Documents/BBI/Workspace_fun/Android/diet-tracker/app/src/main/java/com/chandilsachin/diettracker/database/Food.kt
Error:(1, 1) Some error(s) occurred while processing annotations. Please see the error messages above.
Error:Execution failed for task ':app:kaptDebugKotlin'.
> Compilation error. See log for more details
Information:BUILD FAILED in 10s
Information:2 errors
Information:2 warnings
Information:See complete output in console
I am attaching my gradle file also:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.chandilsachin.diettracker"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.github.ne1c:rainbowmvp:1.2.1'
compile "org.jetbrains.anko:anko-commons:0.10.0"
/*annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"*/
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
Has anyone come across this issue?
After spinning my head around for a while with this problem, I came across to the solution.
It was really hard as there is no official tutorial, blog etc out there to help with this problem as of now.
I had to do several hit and trial for all the combination of gradle plugins and dependencies as i knew that something is wrong with gradle config only.
Lets come to the solution:
I had to remove apply plugin: 'kotlin-kapt' from build.gradle(:module) file
and replace annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1" to kapt "android.arch.persistence.room:compiler:1.0.0-alpha1".
This is the gradle configuration to successfully compile code.
But there more things to check. You have to initialise properties of your #Entity class unlike java given in Room Persistence lib doc. Though there are getter setter but it is not mentioned to create a constructor with initialisation.
So I had to change my #Entity class with this:
#Entity(tableName = "all_food_list")
class Food (#ColumnInfo(name = "food_name") var foodName: String = "",
#ColumnInfo(name = "food_desc") var foodDesc: String = "",
#ColumnInfo(name = "protein") var protein: Double = 0.0,
#ColumnInfo(name = "carbs") var carbs: Double = 0.0,
#ColumnInfo(name = "fat") var fat: Double = 0.0,
#ColumnInfo(name = "calories") var calories: Double = 0.0)
{
#ColumnInfo(name = "id")
#PrimaryKey(autoGenerate = true)
var id: Long = 0
}
Now for TypeConverts, Unlike java, you need to create normal function not static functions(companion object):
class Converters{
#TypeConverter
fun fromTimestamp(value: String): Calendar {
val arr = value.split("-")
val cal = Calendar.getInstance()
cal.set(arr[0].toInt(), arr[1].toInt(), arr[2].toInt())
return cal
}
#TypeConverter
fun dateToTimestamp(date: Calendar): String {
return "${date.get(Calendar.DATE)}-${date.get(Calendar.MONTH)+1}-${date.get(Calendar.YEAR)}"
}
}
I am adding build.gradle file also to make it more clear:
build.gradle(:project)
buildscript {
ext.kotlin_version = '1.1.2-4'
ext.gradle_version_stable = '2.3.2'
ext.gradle_version_preview = '3.0.0-alpha1'
ext.anko_version = '0.10.0'
repositories {
maven { url 'https://maven.google.com' }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven { url 'https://maven.google.com' }
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle(:module)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.chandilsachin.diettracker"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
...
...
// room persistence dependency
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
I think this is all, I did to make my code woking.
Hope this helps someone else also.
man just add the following in the build.gradle. Above dependencies :D
kapt {
generateStubs = true
}
Related
What is going on with RoomDB and Kotlin coroutines? I am trying, again and again, to use suspend function in Room Dao but every time it shows an error. I even follow the android codelabs example. But it shows an error again. the app doesn't even build if I write suspend in Dao. But if I remove suspend keyword it builds successfully.
It shows the error below:
error: Type of the parameter must be a class annotated with #Entity or a collection/array of it.
kotlin.coroutines.Continuation<? super kotlin.Unit> continuation);
My Entity:
import androidx.room.Entity
import androidx.room.PrimaryKey
#Entity(tableName = "vocabulary")
class Vocabulary(
#PrimaryKey(autoGenerate = true)
val vocabularyId: Long,
val word: String,
val meaning: String,
val definition: String,
val example: String,
val partsOfSpeech: String,
val synonyms: String,
val antonyms: String,
val phonetics: String,
val folderId: Long,
val isLearned: Int
)
My Dao:
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
#Dao
interface VocabuilderDao {
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertVocab(vocabulary: Vocabulary)
}
My Database class:
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
#Database(entities = [Vocabulary::class], version = 1, exportSchema = false)
public abstract class VocabuilderRoomDb : RoomDatabase(){
abstract fun vocabuilderDao(): VocabuilderDao
companion object{
#Volatile
private var INSTANCE: VocabuilderRoomDb? = null
fun getRoomDatabase(context: Context): VocabuilderRoomDb{
return INSTANCE ?: synchronized(this){
val instance = Room.databaseBuilder(
context.applicationContext,
VocabuilderRoomDb::class.java,
"vocabuilder_roomdb"
).build()
INSTANCE = instance
instance
}
}
}
}
My build.gradle (project level):
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.6.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
ext {
activityVersion = '1.2.3'
appCompatVersion = '1.3.0'
constraintLayoutVersion = '2.0.4'
coreTestingVersion = '2.1.0'
coroutines = '1.5.0'
lifecycleVersion = '2.3.1'
materialVersion = '1.3.0'
roomVersion = '2.3.0'
// testing
junitVersion = '4.13.2'
espressoVersion = '3.1.0'
androidxJunitVersion = '1.1.2'
}
task clean(type: Delete) {
delete rootProject.buildDir
}
My build.gradle(module):
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.domesoft.vocabuilder"
minSdk 21
targetSdk 31
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
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
// Dependencies for working with Architecture components
// You'll probably have to update the version numbers in build.gradle (Project)
// Room components
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
kapt "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-common-java8:$rootProject.lifecycleVersion"
// Kotlin components
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.coroutines"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.coroutines"
// UI
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
implementation "com.google.android.material:material:$rootProject.materialVersion"
// Testing
testImplementation "junit:junit:$rootProject.junitVersion"
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
androidTestImplementation ("androidx.test.espresso:espresso-core:$rootProject.espressoVersion", {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestImplementation "androidx.test.ext:junit:$rootProject.androidxJunitVersion"
}
If you using kotlin version (1.7.0) shoud work with room latest alpha version (2.5.0-alpha02)
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0"
implementation "androidx.room:room-runtime:2.5.0-alpha02"
implementation "androidx.room:room-ktx:2.5.0-alpha02"
kapt "androidx.room:room-compiler:2.5.0-alpha02"
If you want using room in stable version (2.4.2) should work with kotlin version (1.6.20)
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20"
implementation "androidx.room:room-runtime:2.4.2"
implementation "androidx.room:room-ktx:2.4.2"
kapt "androidx.room:room-compiler:2.4.2"
I have tried both and they work. this is the reference: issue tracker
Update the Room version to 2.4.0-rc01.
In my case it solved the problem, and it works with Kotlin 1.6.0.
For me, kotlin-gradle-plugin 1.6.0 didn't work:
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
but 1.5.31 worked:
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31'
Kotlin 1.6.0 with Room 2.4.0-rc01 worked too.
Thanks Stefano.
I have looked at the solutions presented at each of these links.
NonExistentClass cannot be converted to Annotation - app:kaptDebugAndroidTestKotlin
-- Not relevant as I am not using JUnit5.
error: incompatible types: NonExistentClass cannot be converted to Annotation #error.NonExistentClass()
-- Two issues, one is I don't know where to put kapt { } and I tried leaving it as a global, but that didn't do anything and putting it in dependency caused a error.
NonExistentClass cannot be converted to Annotation
-- Unsure where to set generateStubs to true and where to set correctErrorTypes to true in my build.gradle file. I don't know if I can use annotationProcessor on it's own.
On my own I tried to implement android.arch before realizing it is deprecated.
I tried to use ksp but that returned an error stating that the complier doesn't know where the ksp() method is. Using
implementation("com.google.devtools.ksp:symbol-processing-api:1.5.0-1.0.0-alpha10")
did not resolve the error with ksp.
The error message exactly: "error: incompatible types: NonExistentClass cannot be converted to Annotation"
#error.NonExistentClass()
Here is my module build.gradle
plugins {
id 'com.android.application'
// id 'com.android.feature'
id 'kotlin-android'
id 'kotlin-kapt'
//id 'dagger.hilt.android.plugin'
//id 'kotlin-ksp'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android'
//apply plugin: 'dagger.hilt.android.plugin'
//apply plugin: 'com.android.feature'
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.testingdatabases"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
kapt {
correctErrorTypes = true
}
}
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'
}
}
dependencies {
// ROOM - -- - --- - - - >
def room_version = "2.3.0"
implementation("androidx.room:room-runtime:$room_version")
annotationProcessor "androidx.room:room-compiler:$room_version"
// To use Kotlin annotation processing tool (kapt)
kapt("androidx.room:room-compiler:$room_version")
// To use Kotlin Symbolic Processing (KSP)
// ksp("androidx.room:room-compiler:$room_version")
// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$room_version")
api("io.grpc:grpc-kotlin-stub:1.0.0")
// implementation("com.google.devtools.ksp:symbol-processing-api:1.5.0-1.0.0-alpha10")
// < -- - - - End of Room stuff
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
Here is the project's build.gradle file,
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.0"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
def nav_version = "2.3.0-alpha01"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Here is the applications code,
package com.example.testingdatabases
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.room.RoomDatabase;
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
#Entity
data class User(
#PrimaryKey val uid: Int,
#ColumnInfo(name = "first_name") val firstName: String?,
#ColumnInfo(name = "last_name") val lastName: String?
)
#Dao
interface UserDao {
#Query("SELECT * FROM user")
fun getAll(): List<User>
#Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun loadAllByIds(userIds: IntArray): List<User>
#Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
"last_name LIKE :last LIMIT 1")
fun findByName(first: String, last: String): User
#Insert
fun insertAll(vararg users: User)
#Delete
fun delete(user: User)
}
#Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
in gradle implementation "a-b-x" is used and in kotlin dsl implemntation("a-b-x") is used ,don't mix
Your database is not build properly (According to me) Here
I'm trying to get LiveData from Room. So my RecycleView can have Live updates if anything in database is changed
I have tried with out LiveData and that works, but when i add LiveData that always shows this error.
error: Not sure how to convert a Cursor to this method's return type (androidx.lifecycle.LiveData<java.util.List<com.example.models.Club>>).
public abstract java.lang.Object getAll(#org.jetbrains.annotations.NotNull()
I googled and looked on this site for solution, but every on with this issue have used rxjava, rxandroid, rxkotlin or ArrayList.
And for them solution is to replace ArrayList with List, and for RX to try coroutine.
Well i am using Coroutine and List and still no progress.
This is my ClubDao
ClubDao
#Query("SELECT * FROM club")
suspend fun getAll(): LiveData<List<Club>>
In Club i have this attributes
Club
#Entity
data class Club(#PrimaryKey var id: Int,
#ColumnInfo(name = "logo_url") var logoUrl: String,
#ColumnInfo(name = "name") var name: String,
#ColumnInfo(name = "town") var town: String,
#ColumnInfo(name = "address") var address: String,
#ColumnInfo(name = "contact_name") var contactName: String,
#ColumnInfo(name = "phone_numbers") var phoneNumbers: String,
#ColumnInfo(name = "email") var email: String)
phoneNumbers should be List, but i convert those to and from json with TypeConverters
TypeConverter is here
TypeConverter
class ConvertersDB {
#TypeConverter
fun fromString(value: String): ArrayList<String> {
val listType = object : TypeToken<ArrayList<String>>() {
}.type
return Gson().fromJson(value, listType)
}
#TypeConverter
fun fromArrayList(list: ArrayList<String>): String {
val gson = Gson()
return gson.toJson(list)
}
}
And my DB
DataBase
#Database(entities = [Club::class], version = 1, exportSchema = false)
#TypeConverters(ConvertersDB::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun clubDao(): ClubDao
companion object {
#Volatile
private var instance: AppDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: buildDatabase(context).also { instance = it }
}
private fun buildDatabase(context: Context) = Room.databaseBuilder(context,
AppDatabase::class.java, "pss.db")
.allowMainThreadQueries()
.build()
}
}
In my fragment i need to observe all the clubs from database via ViewModel and Repository and send them to RecycleView
Now i am getting error:
error: Not sure how to convert a Cursor to this method's return type (androidx.lifecycle.LiveData<java.util.List<com.example.models.Club>>).
public abstract java.lang.Object getAll(#org.jetbrains.annotations.NotNull()
Does anyone know solution for this?
EDIT:
Gradle
apply plugin: 'com.android.application'
apply plugin: 'androidx.navigation.safeargs'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.overswayit.plesnisavezsrbije"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dataBinding {
enabled true
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31"
implementation 'com.jakewharton:butterknife:10.1.0'
implementation 'com.google.android.material:material:1.1.0-alpha07'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
// Room components
implementation "androidx.room:room-runtime:$rootProject.roomVersion"
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
kapt "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Room and RxJava
implementation "androidx.room:room-rxjava2:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:$rootProject.archLifecycleVersion"
kapt "androidx.lifecycle:lifecycle-compiler:$rootProject.archLifecycleVersion"
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.androidxArchVersion"
// ViewModel Kotlin support
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.archLifecycleVersion"
//LiveData Kotlin
implementation "androidx.lifecycle:lifecycle-livedata:$rootProject.archLifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.archLifecycleVersion"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$rootProject.archLifecycleVersion"
// Coroutines
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.coroutines"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.coroutines"
//RxJava
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation "io.reactivex.rxjava2:rxjava:2.2.6"
implementation 'com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2'
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.3.31"
annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.kaopiz:kprogresshud:1.0.5'
implementation 'com.squareup:otto:1.3.8'
implementation 'agency.tango.android:avatar-view:0.0.2'
implementation 'agency.tango.android:avatar-view-picasso:0.0.2'
implementation 'com.mikhaellopez:circularimageview:3.2.0'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.1.0'
// Data Binding
kapt "com.android.databinding:compiler:3.1.4"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(path: ':tuple')
// Navigation Component
implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.0.0'
//Gson
implementation 'com.google.code.gson:gson:2.8.5'
}
kapt {
generateStubs = true
}
Top Level Gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.31"
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
roomVersion = '2.1.0'
archLifecycleVersion = '2.2.0-alpha01'
androidxArchVersion = '2.0.0'
coroutines = '1.2.0'
}
As mentioned in the comments, remove suspend.
When a method returns an observable, there is no reason to make it suspend since it just returns and object, does not run any query until it is observed.
#Query("SELECT * FROM club")
fun getAll(): LiveData<List<Club>>
Room's coroutines integration brings ability to return suspend values but when the value itself is asnyc, there is no reason to use it.
I found a good solution to the problem with using rxJava with room and livedata.
The approach is similar to using Retrofit with RxJava, using LiveDataReactiveStreams, which
by default uses flowable.
In your approach i would recomend is:
#Query("SELECT * FROM club")
suspend fun getAll(): LiveData<List<Club>>
changed to
DAO:
#Query("SELECT * FROM club")
fun getAll(): (Any rxJava object) Flowable<List<Club>>
Repository:
fun getAllClubs() : LiveData<List<Club>>{
return LiveDataReactiveStreams.fromPublisher(dao.getAll()"do any transformation or
other functionality you want and then if using Maybe for example transform to
flowable by .toFlowable()")
}
ViewModel:
val clubList : MediatorLiveData<List<Club>>()
fun setClubData(){
clubList.addSource(repository.getAllClubs(), {
clubList.value = it
})
}
then you can observe the livedata object as usual in your view.
Hope what i wrote is understandable, if not i will try to make it better :)
UPDATE: tried Mike's suggestion, still get error:
ext {
kotlin_version = '1.1.50'
arch_lib_version = '1.0.0-alpha9'
gradle_version = '2.3.3'
}
kapt {
generateStubs = true
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile "android.arch.lifecycle:runtime:$arch_lib_version"
compile "android.arch.lifecycle:extensions:$arch_lib_version"
compile "android.arch.persistence.room:runtime:$arch_lib_version"
//annotationProcessor "android.arch.persistence.room:compiler:$arch_lib_version"
kapt "android.arch.persistence.room:compiler:$arch_lib_version"
annotationProcessor "android.arch.lifecycle:compiler:$arch_lib_version"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
Error:Annotation processor '__gen.AnnotationProcessorWrapper_robotiumDebug_android_arch_persistence_room_RoomProcessor' not found
============
in gradle:
ext {
arch_lib_version = '1.0.0-alpha9'
}
compile "android.arch.persistence.room:runtime:$arch_lib_version"
annotationProcessor "android.arch.persistence.room:compiler:$arch_lib_version"
//kapt "android.arch.persistence.room:compiler:$arch_lib_version"
tried using the kapt, it will give compile error:
Error:Annotation processor '__gen.AnnotationProcessorWrapper_robotiumDebug_android_arch_persistence_room_RoomProcessor' not found
the code snippet is below:
#Database(entities = arrayOf(CModel::class), version = 1)
abstract class CDatabase : RoomDatabase() {
abstract fun cModel(): DbCDao
companion object {
fun getDatabase(context: Context): CDatabase {
return Room.databaseBuilder(context.applicationContext, CDatabase::class.java, “database”)
.build() //<=== throw here saying CDatabase_Impl does not exist
}
}
}
the table clas:
#Entity(tableName = “table”)
class CModel() : ICDelegate {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = “index")
private var mIndex: Long = -1
#ColumnInfo(name = "parentIndex")
private var mParentIndex: Long = -1
……
}
the Dao interface defination:
#Dao
interface DbCDao {
#Query("select * from table")
fun loadAllAccountss(): List<CModel>
#Query("select * from table where index = :index")
fun loadCsByIndex(index: Int): CModel
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertC(ac: CModel) : Long
#Update(onConflict = OnConflictStrategy.REPLACE)
fun updateAC(ac: CModel) : Int
#Delete
fun deleteAc(ac: CModel) : Int
#Query("DELETE FROM table”)
fun deleteAllCs()
}
the exception:
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by:
java.lang.RuntimeException: cannot find implementation for com.myproject.data. CDatabase. CDatabase_Impl does not exist
at
android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90)
at
android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:440)
tried someone suggested and does not work:
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
This is my workable build.gradle file:
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
...
kapt {
generateStubs = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'commons-io:commons-io:2.5'
compile "android.arch.persistence.room:runtime:1.0.0-alpha9-1"
kapt "android.arch.persistence.room:compiler:1.0.0-alpha9-1"
}
Take into account:
apply plugin: 'kapt' is removed.
kapt {
generateStubs = true
}
compile instead on implementation.
I used Kotlin 1.1.50.
I am implementing Room persistence lib in kotlin for my database implementation.
Following are my Entity, Dao and Database classes:
Food.kt
#Entity
class Food(#ColumnInfo(name = "food_name") var foodName: String,
#ColumnInfo(name = "food_desc") var foodDesc: String,
#ColumnInfo(name = "protein") var protein: Double,
#ColumnInfo(name = "carbs") var carbs: Double,
#ColumnInfo(name = "fat") var fat: Double)
{
#ColumnInfo(name = "id")
#PrimaryKey(autoGenerate = true)
var id: Long = 0
#ColumnInfo(name = "calories")
var calories: Double = 0.toDouble()
}
PersonalizedFood.kt
#Entity(primaryKeys = arrayOf("food_id","date"))
class PersonalizedFood(#ColumnInfo(name = "quantity") var quantity: Int,
#ColumnInfo(name = "unit") var unit: String,
#ColumnInfo(name = "date") var date: Date){
#ColumnInfo(name = "food_id")
var foodId:Long = 0
}
FoodDao.kt
#Dao
interface FoodDao {
companion object{
const val ID = "id"
const val NAME = "name"
const val PROTEIN = "protein"
const val DESC = "desc"
const val CARBS = "carbs"
const val FAT = "fat"
const val DATE = "date"
const val FOOD_ID = "food_id"
const val ALL_FOOD_LIST = "food"
const val PERSONALISED_FOOD_LIST = "personalised_food"
}
/**
* Returns food details of a food given by food_id
*/
#Query("SELECT * FROM $ALL_FOOD_LIST WHERE $ID=:food_id")
fun getFoodDetails(food_id:Long):Food
/**
* Inserts food items in all_food_list
*/
#Insert
fun addFoodList(list:ArrayList<Food>)
#Insert(onConflict = REPLACE)
fun saveFood(food:PersonalizedFood)
#Query("SELECT * FROM $PERSONALISED_FOOD_LIST WHERE $FOOD_ID=:foodId and $DATE=:date")
fun getFood(foodId:Int, data:Date):PersonalizedFood
#Query("SELECT * FROM $ALL_FOOD_LIST where $ID in (select $FOOD_ID from $PERSONALISED_FOOD_LIST where $DATE = :date)")
fun getFood(date:Date):ArrayList<Food>
}
Converter.kt
class Converter {
companion object{
#TypeConverter
fun fromTimestamp(value: Long?): Date? {
return if (value == null) null else Date(value)
}
#TypeConverter
fun dateToTimestamp(date: Date): Long {
return date.time
}
}
}
FoodDatabase.kt
#Database(entities = arrayOf(Food::class, PersonalizedFood::class), version = 1)
#TypeConverters(Converter::class)
abstract class FoodDatabase : RoomDatabase(){
abstract fun foodDao():FoodDao
companion object{
private val databaseName = "diet"
var dbInstance:FoodDao? = null
fun getInstance(context:Context):FoodDao?{
if(dbInstance == null)
dbInstance = Room.inMemoryDatabaseBuilder(context, FoodDatabase::class.java).build().foodDao()
return dbInstance;
}
}
}
And when i run following code to create database:
FoodDatabase.getInstance(baseContext)?.getFood(Calendar.getInstance().time)
It gives me following exception:
Caused by: java.lang.RuntimeException: cannot find implementation for
com.chandilsachin.diettracker.database.FoodDatabase. FoodDatabase_Impl
does not exist
at
android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90)
at
android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:340)
at
com.chandilsachin.diettracker.database.FoodDatabase$Companion.getInstance(FoodDatabase.kt:21)
at
com.chandilsachin.diettracker.MainActivity$SetUpFoodDatabase.doInBackground(MainActivity.kt:95)
at
com.chandilsachin.diettracker.MainActivity$SetUpFoodDatabase.doInBackground(MainActivity.kt:77)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Has anyone implemented room persistence in kotlin?
Edited
This question was marked duplicate of this. Though problem statement is same but solution given does not solve my problem. Solution says i have to add replace annotationProcessor to kapt "android.arch.persistence.room:compiler:1.0.0-alpha1" dependency. I made those changes and it resulted in gradle error while project build.
Information:Gradle tasks [:app:assembleDebug] Warning:warning:
Supported source version 'RELEASE_7' from annotation processor
'android.arch.persistence.room.RoomProcessor' less than -source '1.8'
Warning:warning: The following options were not recognized by any
processor: '[kapt.kotlin.generated]'
/Users/BBI-M1025/Documents/BBI/Workspace_fun/Android/diet-tracker/app/src/main/java/com/chandilsachin/diettracker/database/Food.kt
Error:(1, 1) Some error(s) occurred while processing annotations. Please see the error messages above.
Error:Execution failed for task ':app:kaptDebugKotlin'.
Compilation error. See log for more details
Information:BUILD FAILED in 10s
Information:2 errors
Information:2 warnings
Information:See complete output in console
I am attaching my gradle file also:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.chandilsachin.diettracker"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.github.ne1c:rainbowmvp:1.2.1'
compile "org.jetbrains.anko:anko-commons:0.10.0"
/*annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"*/
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
Has anyone come across this issue?
After spinning my head around for a while with this problem, I came across to the solution.
It was really hard as there is no official tutorial, blog etc out there to help with this problem as of now.
I had to do several hit and trial for all the combination of gradle plugins and dependencies as i knew that something is wrong with gradle config only.
Lets come to the solution:
I had to remove apply plugin: 'kotlin-kapt' from build.gradle(:module) file
and replace annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1" to kapt "android.arch.persistence.room:compiler:1.0.0-alpha1".
This is the gradle configuration to successfully compile code.
But there more things to check. You have to initialise properties of your #Entity class unlike java given in Room Persistence lib doc. Though there are getter setter but it is not mentioned to create a constructor with initialisation.
So I had to change my #Entity class with this:
#Entity(tableName = "all_food_list")
class Food (#ColumnInfo(name = "food_name") var foodName: String = "",
#ColumnInfo(name = "food_desc") var foodDesc: String = "",
#ColumnInfo(name = "protein") var protein: Double = 0.0,
#ColumnInfo(name = "carbs") var carbs: Double = 0.0,
#ColumnInfo(name = "fat") var fat: Double = 0.0,
#ColumnInfo(name = "calories") var calories: Double = 0.0)
{
#ColumnInfo(name = "id")
#PrimaryKey(autoGenerate = true)
var id: Long = 0
}
Now for TypeConverts, Unlike java, you need to create normal function not static functions(companion object):
class Converters{
#TypeConverter
fun fromTimestamp(value: String): Calendar {
val arr = value.split("-")
val cal = Calendar.getInstance()
cal.set(arr[0].toInt(), arr[1].toInt(), arr[2].toInt())
return cal
}
#TypeConverter
fun dateToTimestamp(date: Calendar): String {
return "${date.get(Calendar.DATE)}-${date.get(Calendar.MONTH)+1}-${date.get(Calendar.YEAR)}"
}
}
I am adding build.gradle file also to make it more clear:
build.gradle(:project)
buildscript {
ext.kotlin_version = '1.1.2-4'
ext.gradle_version_stable = '2.3.2'
ext.gradle_version_preview = '3.0.0-alpha1'
ext.anko_version = '0.10.0'
repositories {
maven { url 'https://maven.google.com' }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven { url 'https://maven.google.com' }
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle(:module)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.chandilsachin.diettracker"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
...
...
// room persistence dependency
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
I think this is all, I did to make my code woking.
Hope this helps someone else also.
Here my gradle files, i didn't need to add thoses plugins.
build.gradle(project):
buildscript {
ext.kotlin_version = '1.1.2-4'
ext.lifecycle_version = '1.0.0-alpha1'
ext.room_version = '1.0.0-alpha1'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
build.gradle (app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
//enable anotation processing with kotlin, disabled by default
kapt {
generateStubs = true
}
android {
/**
...
**/
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
//kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
//support
compile 'com.android.support:appcompat-v7:25.3.1'
//google architecture
compile "android.arch.lifecycle:runtime:$lifecycle_version"
compile "android.arch.lifecycle:extensions:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
kapt "android.arch.lifecycle:compiler:$lifecycle_version"
//database
compile "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
kapt "android.arch.persistence.room:compiler:$room_version"
}
repositories {
mavenCentral()
}
Then run menu build-> make project to create impl class.
Hope this helps
I made an example similar using Java and used to have same problem and solution was add APT line apt "android.arch.persistence.room:compiler:1.0.0-alpha1"
without apply: apply plugin: 'kotlin-kapt'. Remove this line!!
You have to clear project and rebuild it before run again and try uninstall existing app on phone or Virtual device.
Hope you help.
I got the same issue when I try to migrate from Java to Kotlin:
RuntimeException: cannot find implementation for AppDatabase. AppDatabase_Impl does not exist
I tried all these answers in this question, none all them works, then I found an article: Kotlinlang Tutorials - Android Frameworks Using Annotation Processing:
In Kotlin you specify the dependencies in a similar to Java way using Kotlin Annotation processing tool (kapt) instead of annotationProcessor.
Then I modified the build.gradle(Module:app) by changing all annotationProcessor to kapt, it works:
--- a/app/build.gradle
+++ b/app/build.gradle
## -2,6 +2,8 ## apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
// Butter Knife
implementation "com.jakewharton:butterknife:$butterknife_version"
- annotationProcessor "com.jakewharton:butterknife-compiler:$butterknife_version"
+ kapt "com.jakewharton:butterknife-compiler:$butterknife_version"
// Room
implementation "android.arch.persistence.room:runtime:$arch_lifecycle_version"
- annotationProcessor "android.arch.persistence.room:compiler:$arch_lifecycle_version"
+ kapt "android.arch.persistence.room:compiler:$arch_lifecycle_version"
// LifeCycle
implementation "android.arch.lifecycle:runtime:$arch_lifecycle_version"
implementation "android.arch.lifecycle:extensions:$arch_lifecycle_version"
implementation "android.arch.lifecycle:common-java8:$arch_lifecycle_version"
- annotationProcessor "android.arch.lifecycle:compiler:$arch_lifecycle_version"
+ kapt "android.arch.lifecycle:compiler:$arch_lifecycle_version"
// Dagger
implementation "com.google.dagger:dagger:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
- annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
- annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
+ kapt "com.google.dagger:dagger-compiler:$dagger_version"
+ kapt "com.google.dagger:dagger-android-processor:$dagger_version"
}
If you use Butter Knife, you should also change to kapt, otherwise the views which are injected might be null.
in the Dao interface check that the annotations like #Query .. are imported from the room database class and not from somewhere else