文章目录
- 项目添加ksp插件
- 添加 room 引用
- 开始使用room
- 1. 创建bean
- 2. 创建 dao类
- 3. 创建database类
- 数据库升级
- 复制数据库到指定路径
- 参考文献
项目添加ksp插件
注意,因为ksp插件 是跟项目中使用的kotlin的版本要保持一致的,否则会报错的
- 首先我们去 https://github.com/google/ksp/releases 看一下目前的ksp 的版本是多少,我当时用的时候的版本是
2.0.0-1.0.22
,这里的版本数字代表的意思是kotlin的版本是2.0.0,ksp的版本是1.0.22
2. 我们打开项目的gradle/libs.versions.toml
文件,如下,我们看到我们使用的kotlin版本是1.9.0
,所以我们需要把kotlin的版本升级成2.0.0
注意: 如果我们在同步项目的时候发现报如下错误的时候,我们可以在
settings.gradle.kts
文件中配置阿里的maven
添加如下代码
pluginManagement {
repositories {
...
maven { setUrl("https://maven.aliyun.com/nexus/content/groups/public/") }
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
...
repositories {
maven { setUrl("https://maven.aliyun.com/nexus/content/groups/public/") }
google()
mavenCentral()
}
}
- 在项目的
build.gradle.kts
文件中添加引用,如下:plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.jetbrainsKotlinAndroid) apply false // apply false 的意思是代表gradle 不会自动应用这个插件,性能优化 id("com.google.devtools.ksp") version "2.0.0-1.0.22" apply false }
- 在模块的
build.gradle.kts
文件中添加如下代码。这样ksp插件就引入成功了plugins { ... id("com.google.devtools.ksp") }
添加 room 引用
- 在app的
build.gradle.kts
文件中添加引用dependencies { ... implementation("androidx.room:room-runtime:2.6.1") annotationProcessor("androidx.room:room-compiler:2.6.1") // To use Kotlin Symbol Processing (KSP) ksp("androidx.room:room-compiler:2.6.1") // optional - Kotlin Extensions and Coroutines support for Room implementation("androidx.room:room-ktx:2.6.1") }
在项目中你会遇到如下 黄色警告,可以点击下面的replace,它会自动的给你替换成使用
libs.versions.toml
的方式来引用
开始使用room
1. 创建bean
@Parcelize
@Entity(tableName = "person")
data class Person(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
// 指定数据库表中列的名字,如果不指定就默认使用字段的名字
@ColumnInfo(name = "name")
var name: String = "",
var gender: String = "",
var telephone: String = "",
var score: Int = 0,
) : Parcelable
2. 创建 dao类
@Dao
interface PersonDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun addPeople(person: Person)
@Delete
fun delPeople(person: Person)
@Query("delete from person")
fun delAll()
@Update
fun update(person: Person)
@Query("select * from person order by id asc")
fun query(): List<Person>
}
3. 创建database类
方式一
@Database(entities = [Person::class], version = 1, exportSchema = false)
abstract class MyDataBase : RoomDatabase() {
abstract fun personDao(): PersonDao
}
object DataBaseModule {
fun getDb(
context: Context
) = Room.databaseBuilder(
context = context,
MyDataBase::class.java,
"my_database"
)
//允许在主线程中调用
//.allowMainThreadQueries()
.build()
}
方式二
@Database(entities = [Person::class], version = 2, exportSchema = false)
abstract class MyDataBase : RoomDatabase() {
abstract fun personDao(): PersonDao
companion object {
@Volatile
private var INSTANCE: MyDataBase? = null
fun getInstance(context: Context): MyDataBase? {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
MyDataBase::class.java,
"my_database"
)
//允许在主线程中调用
//.allowMainThreadQueries()
.build()
INSTANCE = instance
INSTANCE
}
}
}
}
数据库升级
- 编写
Migration
类// 第一种 更新表结构 val MIGRATION_2_3 = object : Migration(2, 3) { override fun migrate(db: SupportSQLiteDatabase) { db.execSQL("ALTER TABLE person ADD COLUMN score INTEGER not null default 0") } } // 第二种 迁移数据 val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(db: SupportSQLiteDatabase) { //1. 创建一个新表 db.execSQL( """ create table person_temp( id integer not null primary key autoincrement, name text not null , gender text not null, telephone text not null, score integer not null default 0 ) """.trimIndent() ) //2. 迁移数据 db.execSQL( """ insert into person_temp(name,gender,telephone) select name,gender,telephone from person """.trimIndent() ) // 3. 删除旧表 db.execSQL("drop table person") // 4. 重新命名新表 db.execSQL("alter table person_temp rename to person") } }
- 在 database类中以
addMigrations
的方式添加进入object DataBaseModule { fun getDb( context: Context ) = Room.databaseBuilder( context = context, MyDataBase::class.java, "my_database" ) //允许在主线程中调用 //.allowMainThreadQueries() .addMigrations(MIGRATION_1_2) .addMigrations(MIGRATION_2_3) .build() }
复制数据库到指定路径
CoroutineScope(Dispatchers.IO).launch {
val writableDatabase = db.openHelper.writableDatabase
Log.e(TAG, "initListener: ${writableDatabase.path}")
writableDatabase.path?.apply {
// 获取数据库文件路径
val dbFile = File(this)
// 目标文件路径,你可以自定义路径和文件名
val path = Environment.getExternalStorageDirectory().absolutePath
Log.e(TAG, "initListener: $path")
val targetFile = File(path, "copied_database.db")
if (targetFile.exists()) {
targetFile.delete()
}
targetFile.createNewFile()
// 复制数据库文件
try {
Log.e(TAG, "initListener: 开始复制")
val srcChannel: FileChannel = FileInputStream(dbFile).channel
val dstChannel = FileOutputStream(targetFile).channel
dstChannel.transferFrom(srcChannel, 0, srcChannel.size())
srcChannel.close()
dstChannel.close()
Log.e(TAG, "initListener: 复制完成")
} catch (e: IOException) {
e.printStackTrace()
}
}
}
参考文献
1. Room | Jetpack | Android Developer
2. TheRouter 使用 KSP 处理注解
3. Android从Kapt迁移到ksp
4. 可用的KSP的版本