Room 是 Android Jetpack 中的 SQLite 对象映射库,用于简化本地数据库操作,提供编译时 SQL 校验、LiveData/Flow 集成、RxJava 支持等功能。本文将从以下其核心概念、使用示例、适用场景、注意事项及版本兼容性等方面进行讲解。
一、核心组件
1. Entity(实体类)
- 定义数据库表结构,通过注解配置主键、列名、索引等。
2. DAO(Data Access Object)
- 接口或抽象类,定义数据库操作方法(增删改查)。
3. Database(数据库类)
- 继承
RoomDatabase
的抽象类,管理数据库连接和 DAO 实例。
二、使用示例
1. 基础配置
添加依赖:
gradle
// build.gradle (app)
dependencies {
implementation "androidx.room:room-runtime:2.6.1"
kapt "androidx.room:room-compiler:2.6.1"
implementation "androidx.room:room-ktx:2.6.1" // Kotlin扩展
// 可选:RxJava或Paging集成
implementation "androidx.room:room-rxjava3:2.6.1"
implementation "androidx.room:room-paging:2.6.1"
}
2. 定义 Entity
kotlin
@Entity(tableName = "users", indices = [Index(value = ["name"], unique = true)])
data class User(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "name")
val userName: String,
val age: Int,
@ColumnInfo(defaultValue = "false")
val isAdmin: Boolean
)
3. 定义 DAO
kotlin
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)
@Update
suspend fun update(user: User)
@Delete
suspend fun delete(user: User)
@Query("SELECT * FROM users WHERE id = :userId")
fun getUserById(userId: Int): Flow<User?>
@Query("SELECT * FROM users WHERE isAdmin = 1")
fun getAdmins(): PagingSource<Int, User> // 与Paging集成
}
4. 定义 Database
kotlin
@Database(
entities = [User::class],
version = 1,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
@Volatile
private var instance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
return instance ?: synchronized(this) {
instance ?: buildDatabase(context).also { instance = it }
}
}
private fun buildDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database"
).addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
// 数据库首次创建时初始化数据
}
}).build()
}
}
}
5. 在 ViewModel 中操作数据
kotlin
class UserViewModel(private val userDao: UserDao) : ViewModel() {
val admins: Flow<List<User>> = userDao.getAdmins().flowOn(Dispatchers.IO)
fun addUser(name: String, age: Int) {
viewModelScope.launch {
userDao.insert(User(userName = name, age = age))
}
}
}
6. 数据库迁移(版本升级)
kotlin
// 版本1 → 版本2:新增字段 email
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE users ADD COLUMN email TEXT DEFAULT ''")
}
}
// 更新Database配置
Room.databaseBuilder(...)
.addMigrations(MIGRATION_1_2)
.build()
三、适用场景
1. 本地数据持久化
- 用户信息、应用配置、缓存数据等需持久化存储的场景。
2. 复杂查询需求
- 多表关联查询、聚合函数(SUM/COUNT)等。
3. 离线优先架构
- 结合
RemoteMediator
实现先加载本地数据,再同步远程数据。
4. 响应式 UI
- 通过
Flow
或LiveData
监听数据变化,实时更新界面。
四、注意事项
1. 主线程限制
-
默认禁止在主线程执行数据库操作,需使用协程、RxJava 或异步任务。
-
调试时可临时启用
allowMainThreadQueries()
,但生产环境禁用。kotlinRoom.databaseBuilder(...) .allowMainThreadQueries() // 仅用于测试 .build()
2. 索引优化
-
对高频查询字段(如
name
)添加索引,但避免过度索引导致写入性能下降。kotlin@Entity(indices = [Index(value = ["name"], orders = [Order.ASC])])
3. 数据库升级风险
-
修改表结构时需谨慎处理迁移逻辑,建议使用
MigrationTestHelper
进行单元测试。kotlin@Test fun testMigration1To2() { val helper = MigrationTestHelper(...) val db = helper.runMigrationsAndValidate("app_database", 2, true, MIGRATION_1_2) // 验证字段是否存在 }
4. 类型转换
-
复杂类型(如
Date
)需通过TypeConverter
序列化:kotlinclass Converters { @TypeConverter fun fromTimestamp(value: Long?) = value?.let { Date(it) } @TypeConverter fun dateToTimestamp(date: Date?) = date?.time }
在
@Database
注解中添加:kotlin@TypeConverters(Converters::class)
五、版本兼容性
Room 版本 | 最低 Android API | 主要特性 |
---|---|---|
2.2.x | API 16 (Android 4.1) | 支持 Kotlin 协程、预编译数据库。 |
2.4.x | API 16 | 增强 Flow 支持、改进 Paging 3 集成。 |
2.5.x | API 16 | 支持 Upsert 注解、自动迁移(AutoMigration)。 |
2.6.x | API 16 | 提升性能、支持 @Fts4 全文搜索注解。 |
-
AutoMigration(自动迁移)
从 Room 2.4.0 开始,若表结构变更仅涉及新增/删除列,可自动生成迁移逻辑:
kotlin@Database( version = 2, autoMigrations = [ AutoMigration(from = 1, to = 2) ] )
六、与 Hilt 集成(依赖注入)
一文带你了解 Android 中 Dagger/Hilt 的原理和简单使用
kotlin
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
return AppDatabase.getInstance(context)
}
@Provides
fun provideUserDao(database: AppDatabase): UserDao {
return database.userDao()
}
}
// 在 ViewModel 中注入
@HiltViewModel
class UserViewModel @Inject constructor(
private val userDao: UserDao
) : ViewModel() { ... }
七、总结
-
优势:编译时 SQL 校验、与 Jetpack 组件深度集成、简化数据库操作。
-
最佳实践:
- 使用
Flow
或LiveData
实现响应式 UI。 - 通过
TypeConverter
处理复杂数据类型。 - 利用
AutoMigration
简化数据库升级。 - 使用
@Transaction
确保多步骤操作的原子性。
kotlin@Dao interface UserDao { @Transaction suspend fun updateUserName(oldName: String, newName: String) { // 多个操作在一个事务中执行 } }
- 使用
通过合理使用 Room,开发者可以高效管理本地数据,提升应用的稳定性和可维护性。