Room持久化库
Room在SQLite之上提供了一个抽象层,通过这个抽象层可以充分利用SQLite的功能的同时允许更加强大的数据库访问。
这个库帮助你创建app的缓存数据,该缓存作为app唯一真实的数据源,允许用户查看app中关键信息的一致副本,而无需考虑是否有网络连接。
使用Room将数据保存在本地数据库
Room在SQLite上提供了一个抽象层,允许流畅的数据库访问,同时充分利用SQLite的强大功能
本地保存数据对那些需要处理大量结构化数据的app是很有帮助的,最常见的用例是缓存相关的数据,这样当设备无法联网时,用户仍然可以浏览这些被缓存下来的数据,用户发起的任何更改请求都会在重新联网后同步到服务器。
因为Room
帮助你解决这些问题,所以我们强烈建议你使用Room
替代SQLite
,如果更喜欢直接使用SQLite
的APIs,阅读Save Data Using SQLite
Room
中有三种主要的组件
- Database:包含了数据库的持有者,并作为底层持久化关系数据库连接的主要访问点。
被
@Database
注解的类应该满足以下几个条件:- 继承
RoomDatabase
的抽象类 - 在注解中包含与数据库相关联的实体列表
- 包含一个无参的抽象方法,该方法返回被
@Dao
注解的类 在运行时,你可以通过Room.databaseBuilder() or Room.inMemoryDatabaseBuilder().
获取到Database
的实例
- 继承
- Entity:表示实体数据库的一张表
- DAO:包含了访问数据库的方法
App通过Room数据库获得与之相关联的数据访问对象(DAO),然后app通过DAO从数据库中获取实体Entities并且将所有对Entities的更改回写到数据库中去。最终app使用的entity就和数据表的列对应起来了。
Room不同组件之间的关系如下图所示

下面的代码片段包含了一个基本的数据库配置和一个实体Entity,一个数据访问对象DAO
User
@Entity
data class User(
@PrimaryKey val uid: Int,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
UserDao
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAll(): List<User>
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun loadAllByIds(userIds: IntArray): List<User>
@Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
"last_name LIKE :last LIMIT 1")
fun findByName(first: String, last: String): User
@Insert
fun insertAll(vararg users: User)
@Delete
fun delete(user: User)
}
AppDatabase
@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
创建以上文件后,你就通过以下代码获取database
实体。
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "database-name"
).build()
Note:如果你的app是运行在单进程环境中,建议使用单例模式初始化
AppDatabase
对象,每个RoomDatabase
实例的创建都花费巨大,你几乎不需要在单进程中使用到它的多个实例
如果你的app运行在多进程中,记得在
database
的builder
中加上enableMultiInstanceInvalidation()
,这样当你在某个进程中将某个共享数据库文件标记为失效后,这个行为会自动传递到其他进程的database
中