【Kotlin】Android-Room库持久性保存数据简单教程—附demo源码

本文旨在以少量代码和简单逻辑,完整的使用Room,文中demo源码链接附在文末

 特别说明:

        本文采用分—总结构展示代码(除gradle文件),即先展示局部代码,并说明其用法和作用;小节结尾处再给出该部分对应文件的完整代码布局XML源文件在文末。

目录

前言

一.配置数据库

1.添加依赖

2.创建实体数据类

3.创建Dao接口

4.创建数据库抽象类

5.完善Dao

二.MainActivity中调用

1.创建添加、查询函数

 2.设置点击事件

3.真机测试结果

4.实时可视化查看本地数据库

三.布局设置


前言

        谷歌官方提供的Room持久性库,允许更加便捷、流畅的操作本地SQLite数据库,但遗憾的是,官方的说明文档似乎有一段时间没有更新了,其中的示例代码存在一些问题,不能直接照搬到项目中,这会给初次接触Room的初学者造成很大的困扰。

Room需要至少3个类来运行,以及1个注意点

  • 实体数据类:定义数据库中的表
  • Dao接口:创建实际访问数据库的函数
  • 数据库抽象类:声明数据库中的表,创建访问数据库的入口
  • 注意点:访问数据库属于耗时操作,只能在子线程或者协程中进行

一.配置数据库

1.添加依赖

        首先需要在gradle(Moudle)中添加Room所需依赖。

【Kotlin】Android-Room库持久性保存数据简单教程—附demo源码_第1张图片

plugins {
    id 'kotlin-kapt'
}
dependencies {
    // ROOM库
    implementation("androidx.room:room-runtime:2.4.2")
    kapt("androidx.room:room-compiler:2.4.2")
}

2.创建实体数据类

        2.1创建一个Room包,方便管理后续添加的类。

【Kotlin】Android-Room库持久性保存数据简单教程—附demo源码_第2张图片

         2.2创建一个普通的实体数据类,命名为User,本文为方便仅设置3个属性id、name、age

data class User (
    val id: Long=0,
    val name: String,
    val age: Int)

        2.3添加Room的实体类注解。(User的完整代码)

@Entity
data class User (
    @PrimaryKey(autoGenerate = true)
    val id: Long=0,
    val name: String,
    val age: Int)

        直接在类属性上方添加@PrimaryKey(autoGenerate = true)指将此属性设置为表的自增主键(数据库自动赋值,逐渐增大,而我们只要在类中随意设定一个默认值,在实例化此类时,就无需手动给id属性赋值,还省去了确保id值的唯一性的麻烦)。

        其他属性若不加注解,则默认为表中的一个字段。


3.创建Dao接口

        3.1创建一个普通的接口,命名为UserDao

【Kotlin】Android-Room库持久性保存数据简单教程—附demo源码_第3张图片

interface UserDao {
}

        3.2添加Room的Dao注解(只写了一半,后文会完善)

@Dao
interface UserDao {
}

4.创建数据库抽象类

        4.1创建一个普通的抽象类,命名为MyDataBase

【Kotlin】Android-Room库持久性保存数据简单教程—附demo源码_第4张图片

abstract class MyDataBase : RoomDatabase() {
}

        4.2添加Room的数据库注解

@Database(version = 1, entities = [User::class], exportSchema = false)
abstract class MyDatabase : RoomDatabase() {
}

数据库注解的解释:

  • version:数据库版本,未来数据库进行更新升级,其中的表、字段有变更的时候需要依次增加数据库版本,以此告知数据库,其中内容有变化了,否则会报错。
  • entities:获取实体类User,自动定义出一张User表;Room中通过一个实体数据类即可自动定义一张表,若数据库中需要多张表,使用英文逗号分隔即可。(Admin类只用于演示说明,不存在于本demo)
@Database(version = 1, entities = [User::class, Admin::class], exportSchema = false)
  • exportSchema:数据库是否允许导出,在高版本的Android环境中,需要将此项设置为false,禁止导出,否则报错。

        4.3创建访问数据库中User表的入口:即写一个抽象函数返回UserDao对象。

@Database(version = 1, entities = [User::class], exportSchema = false)
abstract class MyDataBase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

        4.4采用单例模式来获取该数据库类,防止多次创建该数据库类对象,开销很大。(MyDataBase的完整代码)

@Database(version = 1, entities = [User::class], exportSchema = false)
abstract class MyDataBase : RoomDatabase() {
    abstract fun userDao(): UserDao

    companion object {
        private var instance: MyDataBase? = null
        @Synchronized
        fun getDataBase(context: Context): MyDataBase {
            return instance
                ?: Room.databaseBuilder(context.applicationContext, MyDataBase::class.java, "any_name_is_ok")
                    .build()
                    .apply { instance = this }
        }
    }
}

5.完善Dao

        向其中添加增删查改的函数。(UserDao的完整代码)

@Dao
interface UserDao {

    @Insert  // 增
    fun insertUser(user: User)

    @Delete  // 删
    fun deleteUser(user: User)

    @Query("select * from user")  // 查
    fun getAllUser(): List

    @Update  // 改
    fun updateUser(user: User)

}

        此时Room的强大优势就显现出来了,仅需添加注解即完成了完全的访问,其中以@Query注解的查询函数可以直接以User类的形式返回数据,无需处理cursor对象,极大的便捷了数据库的操作。

        值得一提的是,自带的@Delete,@Update注解使用场景较为有限,或者说操作权限偏于安全,因为它们要求必须传进来的User对象于库中待修改的User对象的主键值必须一致。比如库中有一个小明,若我试图修改库中小明的年龄信息时,我必须首先得知小明的主键id,这样就不能随便实例化一个User对象来进行增删改的操作。

        但@Query注解支持以SQL语句进行数据库的操作,所以日常使用及定制功能其实完全可以只用@Query注解实现。    


二.MainActivity中调用

1.创建添加、查询函数

        为便于演示,本文不实现依赖于@Delete,@Update注解的逻辑较复杂的删改函数及布局

fun addUser() {
        // 启动一个子线程
        thread {
            // 从数据库类中获取Dao接口,再用Dao访问数据库
            val dao = MyDataBase.getDataBase(this).userDao()
            val user = User(name = "小明", age = 18)
            dao.insertUser(user)
        }
    }
fun queryUser(): String {
        var showText = ""
        // 启动一个子线程
        thread {
            // 从数据库类中获取Dao接口,再用Dao访问数据库
            val dao = MyDataBase.getDataBase(this).userDao()
            val list = dao.getAllUser()
            for (user in list) {
                showText += "名字:${user.name},年龄:${user.age},id:${user.id}\n\n"
            }
        }.join()  // 为了获取子线程中查询到的结果,此处简单的使用join等待子线程完成,再结束函数
        return showText
    }

 2.设置点击事件

// 绑定布局控件,XML文件在后文
val show = findViewById(R.id.show)
val addButton = findViewById

        必须注意的是,访问数据库属于耗时操作,安卓不允许耗时操作在主线程(UI线程)中进行,长时间无响应,会引起页面崩溃,所以对数据库的所有操作都必须在子线程中使用。以下是简单调用子线程的方式。

thread {
// 里面放代码块,就直接启动了一个子线程
}
thread {
// .join()表示等待子线程执行完
}.join()

3.真机测试结果

 

4.实时可视化查看本地数据库

        请移步Android-实时可视化查看本地数据库

        MainActivity的完整代码

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 绑定布局控件,XML文件在后文
        val show = findViewById(R.id.show)
        val addButton = findViewById

 为便于演示,本文不实现依赖于@Delete,@Update注解的逻辑较复杂的删改函数及布局。

三.布局设置

        在约束布局中,简单的设置1个文本框、1个“增”按钮、1个“查”按钮。

【Kotlin】Android-Room库持久性保存数据简单教程—附demo源码_第5张图片

        布局XML文件的完整代码




    

    

如有任何疑问,请在评论区留言,我会努力回复

demo源码 github地址:

https://github.com/darlingxyz/demo_room

你可能感兴趣的:(Android软件开发,kotlin,android-studio,数据仓库,sqlite)