Android jetpack Room的简单使用

项目添加ksp插件

注意,因为ksp插件 是跟项目中使用的kotlin的版本要保持一致的,否则会报错的

  1. 首先我们去 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()
    }
}
  1. 在项目的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
    }
    
  2. 在模块的build.gradle.kts文件中添加如下代码。这样ksp插件就引入成功了
    plugins {
        ...
        id("com.google.devtools.ksp")
    }
    

添加 room 引用

  1. 在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
            }
        }

    }

}

数据库升级

  1. 编写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")
        }
    }
    
  2. 在 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的版本

  • 30
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ljp345775

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值