在日常开放当中,我们肯定会遇到要将数据存储在本地的需求。在Jetpack
全家桶中有提供Room
数据库给我们使用,帮助我们存储数据。这篇博客就说说Room
数据库的知识,希望对看文章的小伙伴有所启发。
Room
Room
是在SQLite
的基础上提供了一个抽象层,让我们充分利用SQLite
的性能同时,还能写出更健壮的数据库相关的代码。
Room相关的依赖
Room基础依赖:
implementation "androidx.room:room-runtime:2.4.2"
annotationProcessor "androidx.room:room-compiler:2.4.2"
配合RxJava2
使用,新增依赖如下:
implementation "androidx.room:room-rxjava2:2.4.2"
配合RxJava3
使用,新增依赖如下:
implementation "androidx.room:room-rxjava3:2.4.2"
配合Paging 3
使用,新增依赖如下:
implementation "androidx.room:room-paging:2.5.0-alpha01"
Room架构图
配图来自网络,如侵必删架构中的相关类和对象:
-
Entity
:一个Entity
对应的是数据库中的一张表。Entity
类是Sqlite
表结构对Java类的映射,在Java中可以被看作一个Model类。 -
Dao
:全称应该是Data Access Objects
,数据访问对象,我们可以通过它来访问数据。
概括就是:
一个Entity代表一张表,而每张表都需要一个Dao对象,用于对表进行增/删/改/查。Room数据库在被实例化之后,我们就可以通过数据库实例得到Dao对象(GetDao),进而通过Dao对象对表中的数据进行操作。
Room字段注解
-
@Entity
:将类和Room中的数据库表对应起来。tableName
属性可以为数据表设置表名,若不设置,则表名与类名相同。 -
@PrimaryKey
:用于指定该字段作为表的主键. -
@ColumnInfo
:设置该字段存储在数据库表中的名字,并指定字段的类型。 -
@Ignore
:告诉Room忽略该字段或方法.
Room简单使用
1.创建一个Entity
类,代码如下:
import androidx.room.PrimaryKey
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
@Entity(tableName = "student")
class Student {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
var id: Int = 0
@ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
var name: String
@ColumnInfo(name = "age", typeAffinity = ColumnInfo.TEXT)
var age: String
/**
* Room默认使用这个构造器操作数据
*/
constructor(id: Int, name: String, age: String) {
this.id = id
this.name = name
this.age = age
}
/**
* 告诉Room忽略这个构造器
*/
@Ignore
constructor(name: String,age: String) {
this.name = name
this.age = age
}
}
2.针对Entity
类,创建一个Dao
类,代码如下:
import androidx.room.*
@Dao
interface StudentDao {
@Insert
fun insertStudent(student: Student?)
@Delete
fun deleteStudent(student: Student?)
@Update
fun updateStudent(student: Student?)
/**
* 查询学生列表
*/
@Query("SELECT * FROM student")
fun studentList(): List<Student>
/**
* 通过id查询某个学生
*/
@Query("SELECT * FROM student WHERE id = :id")
fun getStudentById(id: Int): Student?
}
3.创建数据库代码如下:
import android.content.Context
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.Room
@Database(entities = [Student::class], version = 1)
abstract class MyDatabase : RoomDatabase() {
abstract fun studentDao(): StudentDao
companion object {
private const val DATABASE_NAME = "my_db.db"
@Volatile
private var INSTANCE: MyDatabase? = null
fun getInstance(context: Context): MyDatabase = INSTANCE?: synchronized(this){
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
}
private fun buildDatabase(context: Context) =
Room.databaseBuilder(context.applicationContext, MyDatabase::class.java, DATABASE_NAME)
.allowMainThreadQueries().build()
}
}
4.增删改查
方法:
初始化数据库:
val myDatabase = MyDatabase.getInstance(this)
插入数据:
myDatabase?.studentDao()?.insertStudent(Student("阿博","23"))
更新数据:
myDatabase?.studentDao()?.updateStudent(Student("阿博","24"))
删除数据:
myDatabase?.studentDao()?.deleteStudent(Student("阿博","24"))
查询所有的学生:
myDatabase?.studentDao()?.studentList()
查询单个学生:
myDatabase?.studentDao()?.getStudentById(0)
遇到cannot find implementation for xxxxxx does not exist
遇到这个错误的原因是我们使用Kotlin
开发项目,依赖需要修改成:
kapt "androidx.room:room-compiler:2.4.2"
如果使用这个报错,那就是因为我们项目里面没有使用:
apply plugin: 'kotlin-kapt'
遇到编译错误
Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide room.schemaLocation
annotation processor argument OR set exportSchema to false.
Android官方推荐做法:
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments += [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true"]
}
}
}
}
网友评论