当前位置:网站首页>* Jetpack 笔记 Room 的使用
* Jetpack 笔记 Room 的使用
2022-06-11 18:14:00 【Xia_燚】
前两天我学习的是LifeCycle ViewModel LiveData 以及DataBinding 今天我要学习的是Room

Room的介绍
Android官方ORM库Room
Android采用SQLite作为数据库存储,开源社区常见的ORM(Object Relational Mapping)库有ORMLite GreenDAO 等,Room与其他库一样都是在SQLite上提供一层封装。
Room重要的概念
Entity 实体类,对应的是数据库中的一张表结构,使用注解@Entity标记
Dao 包含访问一系列访问数据库的方法,使用注解@Dao标记
Database 数据库持有者,作为与应用持久化相关数据的底层连接的接入点。使用注解
@Database标记 ,另外需要满足以下条件 定义类必须是一个继承于RoomDatabase的抽象类,在注解中需要定义与数据库相关联的实体类列表。包含一个没有参数的抽象方法并且返回一个Dao对象。

Room的使用
这里我用Kotlin 代码做案例,最后附加上java 代码。
引入依赖库
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "kotlin-kapt"
implementation "androidx.room:room-runtime:2.2.6"
kapt "androidx.room:room-compiler:2.2.6"
implementation "androidx.room:room-ktx:2.2.6"
Room 三大部分概述
Room组要由三大部件组成:@Entity,@Dao和@Database。
简单来讲,@Entity是用来创建具体数据表的,其以数据model类的形式,展现一个数据表中的各个属性。
@Dao是个接口类,一般提供某张表的各种增删改查的方法
@Database作为数据库的根基,数据库文件的位置,数据库的创建都是在此类中完成。@Database注解的类一般会提供一个单例对象,即数据库操作对象,然后会有各个数据表的注册(或声明),以及这些数据表对象的获取的抽象方法放到这个类中。@Database注解的类是一个抽象类。
创建Entity
Kotlin中创建Entity跟Java 差不多,也就是创建一个数据模型给Room去使用,有两种写法 一种是Data 写法 ,还有一种Class 格式,因我我也是最近刚学完的Kotlin 很多地方不是很熟练,比较倾向于 Class格式的写法
@Entity(tableName = "student")
class Student() {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
var name: String = ""
var age: Int = 0
constructor(name: String, age: Int) : this() {
this.name = name
this.age = age
}
constructor(id: Int) : this() {
this.id = id
}
constructor(id: Int, name: String, age: Int) : this() {
this.id = id
this.name = name
this.age = age
}
}
创建Dao
@Dao
interface StudentDao {
@Insert
fun insertStudent(vararg student: Student)
@Delete
fun deleteStudent(vararg students: Student)
@Update
fun updateStudent(vararg students: Student)
@Query("SELECT * FROM student")
fun getAllStudent(): List<Student>
@Query("DELETE FROM student")
fun deleteAllStudents()
// 使用了LiveData 数据变动直接通知页面
@Query("SELECT * FROM student")
fun getAllStudentsLive(): LiveData<List<Student>>
}
创建Database
这是我自己的写法,因为Kotlin 不是很熟练,可能有些地方用的不是很恰当,以后随着我Kotlin的技能不断提升,我会替换的。
@Database(version = 1, exportSchema = false, entities = [Student::class])
abstract class MyDatabase : RoomDatabase() {
companion object {
private val DATABASE_NAME = "my_db.db"
@Volatile
private var mInstance: MyDatabase? = null
@Synchronized
fun getInstance(context: Context): MyDatabase {
mInstance?.let {
return it
}?:let {
mInstance = Room.databaseBuilder(
context.applicationContext,
MyDatabase::class.java,
DATABASE_NAME
).fallbackToDestructiveMigration()
.build()
return mInstance as MyDatabase
}
}
}
abstract fun getStudentDao(): StudentDa
}
Repository类(与Room 无关)
这里我为了方便操作,写了一个Repository类,放在子线程对数据库进行操作,不知道写的是否合理,也希望能遇到大佬帮忙看一下。
class StudentRepository(context: Context) {
/** * 数据处理类, 对数据库的操作属于耗时操作 我这边放在了子线程中处理 * 使用LiveData 随时变更数据 **/
var studentDao: StudentDao
init {
val instance = MyDatabase.getInstance(context)
studentDao = instance.getStudentDao()
}
suspend fun insertStudent(students: Student) = withContext(Dispatchers.IO) {
studentDao.insertStudent(students)
}
suspend fun deleteStudent(students: Student) = withContext(Dispatchers.IO) {
studentDao.deleteStudent(students)
}
suspend fun deleteAllStudents() = withContext(Dispatchers.IO) {
studentDao.deleteAllStudents()
}
suspend fun updateStudent(students: Student) = withContext(Dispatchers.IO) {
studentDao.updateStudent(students)
}
fun getAllStudentsLive(): LiveData<List<Student>> {
return studentDao.getAllStudentsLive()
}
}
viewModel类 (与Room 无关)
class StudentViewModel(application: Application) : AndroidViewModel(application) {
var repository: StudentRepository = StudentRepository(application)
//启用协程处理
fun insertStudent(students: Student) {
viewModelScope.launch {
repository.insertStudent(students)
}
}
fun updateStudent(students: Student) {
viewModelScope.launch {
repository.updateStudent(students)
}
}
fun deleteStudent(students: Student) {
viewModelScope.launch {
repository.deleteStudent(students)
}
}
fun deleteAllStudents() {
viewModelScope.launch {
repository.deleteAllStudents()
}
}
fun getAllStudentsLive(): LiveData<List<Student>> {
return repository.getAllStudentsLive()
}
}
这些就是数据库进行增删改查的操作
Room的升级
例如新增一个Sex字段
@Entity(tableName = "student")
class Student() {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
var name: String = ""
var age: Int = 0
var sex: Int = 0
constructor(name: String, age: Int,sex:Int) : this() {
this.name = name
this.age = age
this.sex = sex
}
constructor(id: Int) : this() {
this.id = id
}
constructor(id: Int, name: String, age: Int) : this() {
this.id = id
this.name = name
this.age = age
}
}
在Database中需要修改
@Database(version = 1, exportSchema = false, entities = [Student::class])
abstract class MyDatabase : RoomDatabase() {
companion object {
private val DATABASE_NAME = "my_db.db"
@Volatile
private var mInstance: MyDatabase? = null
@Synchronized
fun getInstance(context: Context): MyDatabase {
mInstance?.let {
return it
} ?: let {
mInstance = Room.databaseBuilder(
context.applicationContext,
MyDatabase::class.java,
DATABASE_NAME
).addMigrations(migration1to2)
.fallbackToDestructiveMigration()
.build()
return mInstance as MyDatabase
}
}
// 增加的版本更新
private val migration1to2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE student ADD COLUMN 'sex' INTEGER NOT NULL")
}
}
}
abstract fun getStudentDao(): StudentDao
}
fallbackToDestructiveMigration()
当更新失败
设置破坏式迁移,数据与结构全清空
边栏推荐
- Jsfinder, wafw00f installation, nmap configuration (msvcr120.dll file is missing)
- 力扣32题最长有效括号
- Global and Chinese market of web content management software 2022-2028: Research Report on technology, participants, trends, market size and share
- [C语言]对一个数组的元素排序后平移元素
- 力扣39题组合总和
- Feign 共享登录信息进行请求
- H. 264 concept
- 10 ways to reset any user password
- Modern application of LDAP directory server
- SISO decoder for a general (n,n-1) SPC code(补充章节3)
猜你喜欢
![Acwing game 40 [End]](/img/6b/a9ea5e1f9578d21219c69571e8b0f8.jpg)
Acwing game 40 [End]

TR-069 protocol introduction

Cryptology Summary
![Spring 2021 daily question [week7 not finished]](/img/93/582608e18bf6d78c552fa9478cdd77.jpg)
Spring 2021 daily question [week7 not finished]
![[piecemeal knowledge] [network composition] the mobile phone can be connected to the campus network, but the computer can't](/img/a1/7858a0651ddca0dfd187dc128b2036.jpg)
[piecemeal knowledge] [network composition] the mobile phone can be connected to the campus network, but the computer can't

【C】 Compilation preprocessing and environment

labelme进行图片数据标注

How to learn and self-study
![Spring 2021 daily question [week3 not finished]](/img/a4/72f2235d014613d26be0fc3524d236.jpg)
Spring 2021 daily question [week3 not finished]

Async leads to unexpected function results and changes the intention of the original code; await is only valid in async functions and the top level bodies of modules
随机推荐
[C语言]用结构体把最高分的学生输出,可有多个最高分
10 ways to reset any user password
[C语言]用结构体按分数高低降序输出学生的姓名和分数
初识企业级平台
[Golang]力扣Leetcode - 292. Nim 游戏(数学)
力扣34在排序数组中查找元素的第一个和最后一个位置
SQL error injection 1
Experiment 2: write a program and verify that the linear table sequence represents all operations
Easycwmp source code analysis
labelme进行图片数据标注
Why OKR needs to be challenging
Global and Chinese markets for ultra high speed printers 2022-2028: Research Report on technology, participants, trends, market size and share
神经网络与深度学习-2- 机器学习简单示例-PyTorch
DC-DC自举电容(BOOT)几个问题
SISO Decoder for Repetition(补充章节4)
使用Transformers将TF模型转化成PyTorch模型
System learning typescript (V) - joint type
系统的可扩展型
Sqli labs customs clearance hey hey~
SQL报错注入1