(Kotlin)Android Jetpack开发 —— 数据库框架Room简单使用

前期工作:

首先添加依赖:

//room数据库
def roomVersion = "2.3.0"
implementation("androidx.room:room-runtime:$roomVersion")
annotationProcessor("androidx.room:room-compiler:$roomVersion")
// To use Kotlin annotation processing tool (kapt) 添加这个,编译的时候系统会帮我们自动生成代码
kapt("androidx.room:room-compiler:$roomVersion")
// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$roomVersion")

 还需要声明:

defaultConfig {
    applicationId "com.xxx.xxxxxxxxxx"
    ...

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    apply plugin: 'kotlin-kapt'

    javaCompileOptions {
        annotationProcessorOptions {
            arguments = ["room.schemaLocation":
                                 "$projectDir/schemas".toString()]
        }
    }
}

代码实现

1、创建实体对象,一个实体就是一张表(每次修改这个实体的时候数据表都会发生变化):

@Entity(tableName = "table_student")//不声明tableName就会以类名为表明
data class Student(
    @PrimaryKey(autoGenerate = true)//唯一key,自动增加
    var id: Int = 0,
    @ColumnInfo(name = "student_name")//不声明name则以字段名为列表名
    var name: String? = "",
    @ColumnInfo(name = "student_age")
    var age: Int? = 0
) {


    constructor(name: String, age: Int) : this() {
        this.name = name
        this.age = age
    }
}

2、创建抽象Dao,编译的时候系统会帮我们自动生成代码:

加suspend关键字是因为这些接口都需要在子线程里面操作,这里用协程

@Dao
interface StudentDao {
    @Insert
    suspend fun insertStudent(student: Student)

    @Update
    suspend fun updateStudent(student: Student)

    @Delete
    suspend fun deleteStudent(student: Student)

    @Query("select * from table_student where id = :id")
    suspend fun getStudent(id:Int):Student?

    @Query("select * from table_student where student_name like :name")
    suspend fun getStudents(name:String):List<Student>

    @Query("select * from table_student")
    suspend fun getAllStudents():List<Student>
}

3、创建数据库抽象类,编译的时候系统会帮我们自动生成代码:

@Database(entities = [Student::class],version = 1)//每次实体做了修改这个version就要升级,会触发数据库迁移的操作
abstract class MyDb constructor():RoomDatabase(){
    abstract fun getStudentDao():StudentDao
}

4、数据库抽象类的实现只要生成一次,用一个单例来管理:

class MyDateBaseHelper(context: Context) {
    private val build:MyDb = Room
        .databaseBuilder(context, MyDb::class.java, "my_db_test")
        .fallbackToDestructiveMigration()//破坏式迁移数据库(第三步那个version改变的时候触发。这里仅做测试,实际开发需要做数据库的迁移)
//        .allowMainThreadQueries()//允许主线程中操作。默认不允许,如果直接在主线程中操作会崩溃。我们这里用了协程,所以不需要声明这个,实际开发中也保证不要在主线程做这种耗时操作
        .build()

    companion object {
        @Volatile
        private var instance: MyDateBaseHelper? = null
        fun getInstance(context: Context): MyDateBaseHelper? {
            if (instance == null) {
                synchronized(MyDateBaseHelper::class.java) {
                    if (instance == null) {
                        instance = MyDateBaseHelper(context)
                    }
                }
            }
            return instance
        }
    }

    fun getStudentDao():StudentDao{
        return build.getStudentDao()
    }

}

5、在activity中使用:

//插入、删除、修改三个按钮的点击事件,查询在删除和修改里面有体现
private fun btnClick(view: View) {
    when (view.id){
        R.id.btnInsert -> {
            //插入一个学生对象
            if(edit.text.isEmpty()){
                Toast.makeText(this,"no input",Toast.LENGTH_SHORT).show()
                return
            }
            GlobalScope.launch(Dispatchers.Main){
                withContext(Dispatchers.IO){
                    studentDao.insertStudent(Student(edit.text.toString(),20))
                }
                updateList()
            }
        }
        R.id.btnDelete ->{
            //删除id为输入框中值的学生(这里仅作简单测试,没做try-catch,实际开发这个id值确保是数字)
            GlobalScope.launch(Dispatchers.Main){
                val student = getStudent(edit.text.toString().toInt()))//先获取这个学生,再做删除操作
                if(student == null){
                    Toast.makeText(this@RoomTestActivity,"student == null",Toast.LENGTH_SHORT).show()
                    return@launch
                }
                studentDao.deleteStudent(student)
                updateList()
            }
        }
        R.id.btnUpdate ->{
            //更新,把id为输入框中值的那个对象修改名字和年龄
            GlobalScope.launch(Dispatchers.Main){
                val student = getStudent(seekBar.progress)
                if(student == null){
                    Toast.makeText(this@RoomTestActivity,"student == null",Toast.LENGTH_SHORT).show()
                    return@launch
                }
                student.age = 25
                student.name = "updateTest"
                studentDao.updateStudent(student)
                updateList()
            }
        }
    }
}

/**
 * 根据id获取学生
 */
private suspend fun getStudent(id:Int):Student?{
    return withContext(Dispatchers.IO){
        studentDao.getStudent(id)
    }
}

/**
 * 更新UI上的列表
 */
private suspend fun updateList(){
    val list = withContext(Dispatchers.IO){
        studentDao.getAllStudents()
    }
    adapter.submitList(list)
}

就可以了。本人是kotlin新手,如果代码有什么错误或者需要优化的地方麻烦评论探讨。

最后给上demo地址:KotlinStudy: 个人学习demo。只会java的我用kotlin语言边学边写。目前做了个room数据库增删改查的demo,持续更新https://gitee.com/xaehu/KotlinStudy 

猜你喜欢

转载自blog.csdn.net/qq_35584878/article/details/121250124