我在kotlin中为我的数据库实现实现了Room persistence lib。
以下是我的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()
}
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;
}
}
}
当我运行以下代码来创建数据库时:
FoodDatabase.getInstance(baseContext)?.getFood(Calendar.getInstance().time)
它给了我以下例外:
造成:java.lang.RuntimeException:无法找到实现 com.chandilsachin.diettracker.database.FoodDatabase。 FoodDatabase_Impl 不存在 在 android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90) 在 android.arch.persistence.room.RoomDatabase $ Builder.build(RoomDatabase.java:340) 在 com.chandilsachin.diettracker.database.FoodDatabase $ Companion.getInstance(FoodDatabase.kt:21) 在 com.chandilsachin.diettracker.MainActivity $ SetUpFoodDatabase.doInBackground(MainActivity.kt:95) 在 com.chandilsachin.diettracker.MainActivity $ SetUpFoodDatabase.doInBackground(MainActivity.kt:77) 在android.os.AsyncTask $ 2.call(AsyncTask.java:295) 在java.util.concurrent.FutureTask.run(FutureTask.java:237) 在android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:234) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 在 java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:588) 在java.lang.Thread.run(Thread.java:818)
有没有人在kotlin中实施过房间持久性?
被修改
此问题被标记为this的重复。虽然问题陈述是相同的,但解决方案并没有解决我的问题。解决方案说我必须将替换annotationProcessor
添加到kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
依赖项。我做了这些更改,但在项目构建时导致了gradle错误。
信息:Gradle任务[:app:assembleDebug]警告:警告: 来自注释处理器的支持的源版本“RELEASE_7” 'android.arch.persistence.room.RoomProcessor'小于-source'1.8' 警告:警告:任何人都无法识别以下选项 处理器:'[kapt.kotlin.generated]' /Users/BBI-M1025/Documents/BBI/Workspace_fun/Android/diet-tracker/app/src/main/java/com/chandilsachin/diettracker/database/Food.kt 错误:(1,1)处理注释时发生了一些错误。请参阅上面的错误消息。 错误:任务':app:kaptDebugKotlin'执行失败。
编译错误。有关详细信息,请参阅日志 信息:10年内建筑失败 信息:2个错误 信息:2个警告 信息:请参阅控制台中的完整输出
我还附上了我的gradle文件:
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()
}
有没有人遇到过这个问题?
答案 0 :(得分:22)
在遇到这个问题后我的头转了一会儿,我找到了解决方案。
这真的很难,因为目前还没有官方教程,博客等帮助解决这个问题。
我必须为gradle插件和依赖项的所有组合做几次点击和试用,因为我知道gradle配置只有一些问题。
让我们来解决方案:
我不得不从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"
。
这是成功编译代码的gradle配置。
但还有更多要检查的事情。与Room Persistence lib doc中给出的java不同,您必须初始化@Entity class
的属性。虽然有getter setter但是没有提到创建一个带初始化的构造函数。
所以我不得不改变我的@Entity
课程:
@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不同,你需要创建普通函数而不是静态函数(伴随对象):
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文件以使其更清晰:
<强>的build.gradle(:项目)强>
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(:模块)强>
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()
}
我认为这就是全部,我做了我的代码工作。
希望这也有助于其他人。
答案 1 :(得分:1)
这是我的gradle文件,我不需要添加插件。
<强>的build.gradle(项目):强>
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()
}
然后运行menu build-&gt; make project来创建impl类。 希望这有帮助
答案 2 :(得分:0)
我做了一个类似的使用Java的例子,以前有同样的问题和解决方案是添加APT线apt“android.arch.persistence.room:compiler:1.0.0-alpha1”
不申请:申请插件:'kotlin-kapt'。删除这一行!!
您必须清除项目并重新运行才能再次运行,并尝试在手机或虚拟设备上卸载现有应用。 希望你能帮忙。
答案 3 :(得分:0)
当我尝试从Java迁移到Kotlin时,我遇到了同样的问题:
RuntimeException: cannot find implementation for AppDatabase. AppDatabase_Impl does not exist
我在这个问题中尝试了所有这些答案,但都没有用,然后我找到了一篇文章:Kotlinlang Tutorials - Android Frameworks Using Annotation Processing:
在Kotlin中,您可以使用Kotlin注释处理工具(kapt)而不是注解处理器,以类似于Java的方式指定依赖项。
然后我通过将所有annotationProcessor
更改为kapt
来修改build.gradle(Module:app),它可以正常工作:
--- 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"
}
如果使用黄油刀,还应该更改为kapt,否则注入的视图可能为空。
答案 4 :(得分:0)
在Dao界面中,检查诸如@Query ..之类的注释是从会议室数据库类而非其他地方导入的