由于Room使用了大量的APT 技术,从源码的角度来分析并不是非常好,所以关于Room相关的内容的就以使用来进行
关于Room 使用 一共有3大部分
Entity 表
在Room中一个被 @Entity 标识的 实体类 就代表着一张表,可以是使用 tableName = "tsmtest" 来明确表明
示例如下
less
@Entity(tableName = "tsmtest")
class TsmTestEntity {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id:Long?=null
@ColumnInfo(name = "name")
var name:String?=null
@ColumnInfo(name = "address")
var address:String?=null
@ColumnInfo(name = "age")
var age:Int?=null
constructor(name: String?, address: String?, age: Int?) {
this.name = name
this.address = address
this.age = age
}
override fun toString(): String {
return "TsmTestEntity(id=$id, name=$name, address=$address, age=$age)"
}
}
Dao
关于Dao 层使用起来也是非常简单的,只需要使用@Dao 来注解这个类,增删改查方法使用单独的注解,这里面有一点让我特别惊讶,那就是对LiveData 的支持,真的是非常的强大
less
@Dao
interface TsmTestDao {
@Insert
fun insertTsmTest(tsm:TsmTestEntity)
@Delete
fun delete(tsm:TsmTestEntity)
@Update
fun upData(tsm:TsmTestEntity)
@Query("select * from tsmtest where name =:name")
fun getTsm(name: String):TsmTestEntity
@Query("select * from tsmtest")
fun getAllTsm():MutableList<TsmTestEntity>
@Query("select * from tsmtest")
fun getAllLiveData():LiveData<MutableList<TsmTestEntity>>
}
DataBase
在使用DataBase 的过程中,需要由3个注意点 1: 需要给DataBase的类添加一些注解,这个注解包括版本号, 关联哪些Dao等,同时这个类必须继承自 RoomDatabase
2: 这个类必须是抽象类
3: 需要实现getDao 的方法
4: 将DataBase 获取设置单利
例子大致如下
kotlin
@Database(entities = [TsmTestEntity::class], version = 1, exportSchema = false)
abstract class TsmTestDB : RoomDatabase() {
abstract fun getTsmDao():TsmTestDao
companion object{
private var tsmDB:TsmTestDB ?=null
fun getInstance(context: Context):TsmTestDB{
if(tsmDB==null){
synchronized(TsmTestDao::class){
if(tsmDB==null){
tsmDB=Room.databaseBuilder(context.applicationContext,TsmTestDB::class.java,"tsm_test.db")
.allowMainThreadQueries().build()
}
}
}
return tsmDB!!
}
}
}
在使用上就看一下 Room 对LiveData 的支持,以及利用这个我们能做一些什么
kotlin
TsmTestDB.getInstance(this).getTsmDao().getAllLiveData().observe(this) {
it.forEach {item->
Log.i("tian.shm", "1-->${item.toString()}")
}
}
利用LiveData 我们可以监听数据库发生变化,这就让整个流程非常的顺利, 日志如下
bash
2023-10-19 23:29:39.901 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=1, name=Tsm1, address=地址1, age=10)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=2, name=这个需要修改一下, address=地址2, age=20)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=3, name=Tsm3, address=地址3, age=30)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=4, name=Tsm4, address=地址4, age=40)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=5, name=Tsm5, address=地址5, age=50)
示例场景
有一个App ,他是多组件的应用,在没有中间件协调的时候,我们如何通知上层组件数据更新了呢,就比如说用户切换了登录信息,如果每次检查就会造成逻辑的复杂度增加, Room + LiveData 就为我们提供一个完美的解决方案,底层组件直接更新数据库的用户信息,在顶层组件使用 Room 就能监听到
数据库升级
关于 Room 数据库升级也是非常简单的
示例代码如下
kotlin
// 这个里面的 Migration(1, 2) 代表着数据库版本从1 升级到2 ,就会执行一下的语句
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
// 这句话的意思就是在 表中添加一列数据 ,类型为 text 字符
database.execSQL("ALTER TABLE tsmtest " + " ADD COLUMN tsm TEXT ")
}
}
我们需要在DB 初始化的时候使用这个升级的方法
kotlin
fun getInstance(context: Context):TsmTestDB{
if(tsmDB==null){
synchronized(TsmTestDao::class){
if(tsmDB==null){
tsmDB=Room.databaseBuilder(context.applicationContext,TsmTestDB::class.java,"tsm_test.db")
.allowMainThreadQueries()
// 添加升级方法方法
.addMigrations(MIGRATION_1_2)
.build()
}
}
}
return tsmDB!!
}
同时在TsmTestEntity 中添加一个tsm 的数据,
less
@Entity(tableName = "tsmtest")
class TsmTestEntity {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id:Long?=null
@ColumnInfo(name = "name")
var name:String?=null
@ColumnInfo(name = "address")
var address:String?=null
@ColumnInfo(name = "age")
var age:Int?=null
//TODO 版本2新增
@ColumnInfo(name = "tsm")
var tsm:String?=null
constructor(name: String?, address: String?, age: Int?) {
this.name = name
this.address = address
this.age = age
}
override fun toString(): String {
return "TsmTestEntity(id=$id, name=$name, address=$address, age=$age, tsm=$tsm)"
}
}
在没有升级后的版本监听到的数据是
bash
2023-10-19 23:29:39.901 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=1, name=Tsm1, address=地址1, age=10)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=2, name=这个需要修改一下, address=地址2, age=20)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=3, name=Tsm3, address=地址3, age=30)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=4, name=Tsm4, address=地址4, age=40)
2023-10-19 23:29:39.902 26063-26063/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=5, name=Tsm5, address=地址5, age=50)
升级后监听到的数据如下
bash
2023-10-19 23:43:39.335 27342-27342/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=1, name=Tsm1, address=地址1, age=10, tsm=null)
2023-10-19 23:43:39.335 27342-27342/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=2, name=这个需要修改一下, address=地址2, age=20, tsm=null)
2023-10-19 23:43:39.335 27342-27342/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=3, name=Tsm3, address=地址3, age=30, tsm=null)
2023-10-19 23:43:39.335 27342-27342/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=4, name=Tsm4, address=地址4, age=40, tsm=null)
2023-10-19 23:43:39.335 27342-27342/com.tsm.tsmroom I/tian.shm: 1-->TsmTestEntity(id=5, name=Tsm5, address=地址5, age=50, tsm=null)
如何查看 DataBase 里面的 db文件,可以在AndroidStudio 中下载插件 Database Navigator,就可以非常简单的浏览我们的表结构了
步骤大致如下 1: 在plugins 中下载 Database Navigator 插件
2: 在 /data/data/[包名]/databases 中将数据库文件导出
3:双击 Shift 键 搜索 DB 就能看到 DB Browser ,同时也可以在 Project 的左侧工具栏看到这个功能,不过还是快捷键好用一些
4:导入db 文件
5: 链接展示
6:在查看完之后 发现这个db文件无法被删除,原因就是我们的AS 使用了他,需要先断开连接