Kotlin中的Room Persistence lib实现
我在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) @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 }
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)
它给了我以下例外:
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中实现了空间持久性?
编辑这个问题被标记为这个重复。 虽然问题陈述是相同的,但解决方案并不能解决我的问题。 解决方案说我必须添加替换annotationProcessor
到kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
依赖项。 我做了这些更改,并在项目构建时导致了gradle错误。
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文件:
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() }
有没有人遇到过这个问题?
把这个问题旋转了一会儿之后,我碰到了解决办法。
这真的很难,因为现在还没有正式的教程,博客等来帮助解决这个问题。
我不得不对gradle插件和依赖项的所有组合进行一些命中和试用,因为我知道只有gradle配置有问题。
让我们来解决:
我不得不从build.gradle(:module)文件中删除apply plugin: 'kotlin-kapt'
,并用kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
替换annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"
。
这是成功编译代码的gradle配置。
但有更多的事情要检查。 您必须初始化您的@Entity class
属性,这与Room Persistence lib doc中给出的java不同。 虽然有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() }
我想这是所有的,我做了我的代码woking。
希望这也可以帮助别人。
在这里我的gradle文件,我不需要添加thoses插件。
的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() }
然后运行菜单build-> make project来创建impl类。 希望这可以帮助
我做了一个类似的使用Java的例子,并使用了相同的问题和解决方案是添加APT行apt“android.arch.persistence.room:compiler:1.0.0-alpha1”
不适用:应用插件:’kotlin-kapt’。 删除这一行!
您必须先清理项目并重新构建,然后再尝试卸载手机或虚拟设备上的现有应用程序。 希望你帮忙。
在我的情况是有点不同。 我使用AS 3.0.0-beta6 。 Kotlin – 1.1.4-3和1.1.50以及1.0.0-alpha9-1室。 而且因为我使用了gradle 3.0.0,所以我把所有的配置改成了实现,而不是编译 。 它造成问题中所描述的问题出现。 解
替换implementation "android.arch.persistence.room:runtime:1.0.0-alpha9-1"
与compile "android.arch.persistence.room:runtime:1.0.0-alpha9-1"
小费
因为在编辑器中有更好的突出显示,所以使用Java来处理您的DAO。