Kotlin中的Room Persistence lib实现(等级错误) [英] Room Persistence lib implementation in Kotlin(Gradle error)
问题描述
我正在为我的数据库实现在kotlin中实现Room persistence lib. 在 Android Room Persistences库和Kotlin 线程中提出了相同的问题,应用了这些解决方案导致了不同的gradle错误:
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:
以下是我的Entity
,Dao
和Database
类:
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()
}
个性化食品.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)
它给了我以下例外:
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)
有人在kotlin中实现了房间持久性吗?
Has anyone implemented room persistence in kotlin?
已编辑
我先前在同一主题上的问题被标记为此的重复项.虽然问题陈述是相同的,但是给出的解决方案并不能解决我的问题.解决方案说我必须在kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
依赖项中添加替换annotationProcessor
.我进行了这些更改,并在项目构建时导致了gradle错误.
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
我还将附加我的gradle文件:
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()
}
有人遇到这个问题吗?
推荐答案
解决了这个问题一段时间后,我想到了解决方案.
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.
我必须对gradle插件和依赖项的所有组合进行多次测试,因为我知道仅gradle配置有问题.
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.
让我们来解决问题:
我必须从build.gradle(:module)文件中删除apply plugin: 'kotlin-kapt'
并将annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
替换为kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
.
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"
.
这是用于成功编译代码的gradle配置.
This is the gradle configuration to successfully compile code.
但是还有更多要检查的东西.您必须初始化@Entity class
的属性,这与 Room Persistence lib中提供的Java不同doc .尽管有getter setter,但是没有提到创建带有初始化的构造函数.
所以我不得不用这个来改变我的@Entity
类:
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
}
现在可以用于TypeConverts了,与Java不同,您需要创建普通函数而不是静态函数(伴侣对象):
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)}"
}
}
我还要添加build.gradle文件,以使其更清晰:
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.
这篇关于Kotlin中的Room Persistence lib实现(等级错误)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!