当前位置:网站首页>* 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()
当更新失败
设置破坏式迁移,数据与结构全清空
边栏推荐
- 软件需求工程复习
- Explain AI accelerators in detail: GPU, DPU, IPU, TPU... There are infinite possibilities for AI acceleration schemes
- SISO decoder for a general (n,n-1) SPC code(補充章節3)
- SQL报错注入1
- 谈谈远程工作 | 社区征文
- 力扣34在排序数组中查找元素的第一个和最后一个位置
- 密码学概述
- System learning typescript (V) - joint type
- RadioGroup动态添加RadioButton
- NR LDPC 打孔-punctured
猜你喜欢

使用Visdom对损失函数进行监控
![[FAQs for novices on the road] about project management](/img/14/68f5e4cead5573fc932350d8d9b06e.png)
[FAQs for novices on the road] about project management

【无标题】
![[c language] output the students within the specified score range with the structure](/img/40/cbd7fe5aafbaeb6237e6d257455e5e.png)
[c language] output the students within the specified score range with the structure

Sorted circular linked list

async导致函数结果出乎意料,改变原来代码的意图;await is only valid in async functions and the top level bodies of modules

金融银行_催收系统简介

Introduction to social engineering practice

10 ways to reset any user password

NR LDPC 打孔-punctured
随机推荐
Winter vacation daily question 2022 [week1 not finished]
SISO Decoder for Repetition(补充章节4)
求字符串中最大的 3 位相同数字
Reading summary of nacos2.x source code
力扣32题最长有效括号
[C语言]对一个数组的元素排序后平移元素
Explain AI accelerators in detail: GPU, DPU, IPU, TPU... There are infinite possibilities for AI acceleration schemes
网络和并发编程常见面试题
SISO Decoder for SPC (补充章节1)
单选按钮 文字背景同时改变
Common operations of Visio
Is it good or not to open a stock account on the flush? Is it safe?
[Golang]力扣Leetcode - 349. 两个数组的交集(哈希表)
ACL 2022: is it no longer difficult to evaluate word polysemy? A new benchmark "dibimt"
新项目 搭建环境方法
【C】 Compilation preprocessing and environment
使用mysql判断日期是星期几
Modern application of LDAP directory server
Nocturnal installs APK and BP agent
Global and Chinese market of web content management software 2022-2028: Research Report on technology, participants, trends, market size and share