Room框架是谷歌官方开发框架Jetpack的其中一部分,主要目的是简化开发者访问应用自身的SQLite数据库的步骤。
官方对Room库的说明说明:
Room 持久性库在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。具体来说,Room 具有以下优势:
- 提供针对 SQL 查询的编译时验证。
- 提供方便注解,可最大限度减少重复和容易出错的样板代码。
- 简化了数据库迁移路径。
出于这些方面的考虑,我们强烈建议您使用 Room,而不是直接使用 SQLite API。
Room库的架构示意图:
groovydependencies { def room_version = "2.6.1" // room版本 implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" // To use Kotlin annotation processing tool (kapt) kapt "androidx.room:room-compiler:$room_version" // To use Kotlin Symbol Processing (KSP) ksp "androidx.room:room-compiler:$room_version" // optional - RxJava2 support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava3 support for Room implementation "androidx.room:room-rxjava3:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" // optional - Paging 3 Integration implementation "androidx.room:room-paging:$room_version" }
在Room中,一个实体即为一个数据类,对应一个表中的一条记录。因此一个实体类能够对应一个表的结构。
写法示例如下:
kotlin
/**
* 单个文件版本信息
*
* @property rowid 主键Id
* @property fileId 文件Id
* @property filePath 文件具体路径
* @property dateTime 文件更新时间
* @property version 文件版本
*/
// @Fts4 该注解使一个实体能够支持全文搜索 但该注解不支持外键
@Entity(
tableName = "FileVersionInfo", // 实体注解 声明表名
foreignKeys = [ForeignKey( // 实体注解 声明外键 外键可以有多个
entity = FileEntity::class, // 主表对应实体
childColumns = ["fileId"], // 从表的字段
parentColumns = ["rowid"], // 主表中要依赖的具体字段
onUpdate = ForeignKey.CASCADE, // 更新策略
onDelete = ForeignKey.CASCADE // 删除策略
)]
)
data class FileVersionEntity (
@PrimaryKey(autoGenerate = true) // 声明主键
val rowid: Int = 0,
// 文件Id
@ColumnInfo(name = "fileId") // 声明字段
val fileId: Int,
// 文件路径
@ColumnInfo(name = "filePath")
val filePath: String,
// 文件存储日期
@ColumnInfo(name = "dateTime", defaultValue = "DATETIME")
val dateTime: String,
// 文件版本
@ColumnInfo(name = "version")
val version: Long
)
/**
* 单个文件信息
*
* @property rowid 主键Id
* @property fileName 文件名
* @property fileIncidentId 文件关联事件Id
* @property fileTag 文件Tag列表
* @property fileUpdateDateTime 文件最新更新日期
* @property fileLatestVersion 文件最新版本
* @property fileComment 文件说明
* @property fileHash 文件最新版本Hash值
*/
//@Fts4
@Entity(
tableName = "FileInfo",
foreignKeys = [ForeignKey(
entity = IncidentEntity::class,
childColumns = ["fileIncidentId"],
parentColumns = ["rowid"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)]
)
data class FileEntity(
@PrimaryKey(autoGenerate = true)
val rowid: Int = 0,
@ColumnInfo(name = "fileName")
val fileName: String,
@ColumnInfo(name = "fileIncidentId")
val fileIncidentId: Int,
@ColumnInfo(name = "fileTag")
val fileTag: String,
@ColumnInfo(name = "fileUpdateDateTime", defaultValue = "DATETIME")
val fileUpdateDateTime: String,
@ColumnInfo(name = "fileLatestVersion")
val fileLatestVersion: Int,
@ColumnInfo(name = "fileComment")
val fileComment: String,
@ColumnInfo(name = "fileHash")
val fileHash: String,
) {
@Ignore // Ignore注解可以使得room根据实体建表时忽略该字段
val fileVersionInfo: List<FileVersionEntity>? = null
// Entity所需要的DataClass的构造方法只能和表的字段互相匹配 因此需要Ignore的字段不能放在构造方法中
}
/**
* 单个事件信息
*
* @property rowid 主键Id
* @property incidentName 事件名
* @property incidentComment 事件说明
*/
@Entity(tableName = "IncidentInfo")
data class IncidentEntity(
@PrimaryKey(autoGenerate = true)
val rowid: Int = 0,
@ColumnInfo(name = "incidentName")
val incidentName: String,
@ColumnInfo(name = "incidentComment")
val incidentComment: String,
) {
@Ignore
val incidentFileInfo: List<FileEntity>? = null
}
在这里只需要定义DAO接口即可,在接口中的抽象方法声明方法要执行的SQL增删改查操作,其余的代码Room会自动生成。
写法示例如下:
kotlin
数据库类定义了数据库的配置,并且作为应用对SQLite数据库的主要访问点。该数据库类必须是抽象类,必须带有@Database
注解,并且对于与该数据库关联的每个DAO类,该类必须定义一个空参数的抽象方法,并返回DAO类的实例。
写法示例如下:
kotlin
/**
* 数据库类 通过getInstance()获取实例
*
*/
@Database(
entities = [FileVersionEntity::class, FileEntity::class, IncidentEntity::class],
version = 1
) // Database注解 声明数据库
abstract class FileDatabase: RoomDatabase() {
// 这些获取DAO实例的方法必须有
abstract fun fileEntityDAO(): FileEntityDAO // DAO 这一个数据库里可以有多个DAO
abstract fun incidentEntityDAO(): IncidentEntityDAO
abstract fun fileVersionInfoDAO(): FileVersionInfoDAO
// 伴生对象 kotlin的静态方法的写法
companion object {
private var INSTANCE: FileDatabase? = null
/**
* 获取数据库实例 (单例模式)
*
* @param context 上下文
* @return 数据库实例
*/
fun getInstance(context: Context): FileDatabase {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.applicationContext,
FileDatabase::class.java,
"FileReceiveActivity"
).build()
}
return INSTANCE as FileDatabase // 转型
}
}
}
首先必须在应用中获取数据库类和DAO类的实例,之后通过实例在协程中获取数据,再在主线程上更新UI。
本文作者:御坂19327号
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!