Android Jetpack Room 新手使用指南

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

  • 通过 FlowLiveData 监听数据变化,实时更新界面。

四、注意事项

1. 主线程限制

  • 默认禁止在主线程执行数据库操作,需使用协程、RxJava 或异步任务。

  • 调试时可临时启用 allowMainThreadQueries(),但生产环境禁用。

    kotlin 复制代码
    Room.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 序列化:

    kotlin 复制代码
    class 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 组件深度集成、简化数据库操作。

  • 最佳实践

    • 使用 FlowLiveData 实现响应式 UI。
    • 通过 TypeConverter 处理复杂数据类型。
    • 利用 AutoMigration 简化数据库升级。
    • 使用 @Transaction 确保多步骤操作的原子性。
    kotlin 复制代码
    @Dao
    interface UserDao {
        @Transaction
        suspend fun updateUserName(oldName: String, newName: String) {
            // 多个操作在一个事务中执行
        }
    }

通过合理使用 Room,开发者可以高效管理本地数据,提升应用的稳定性和可维护性。

更多分享

  1. 一文吃透Kotlin中冷流(Clod Flow)和热流(Hot Flow)
  2. 一文带你吃透Kotlin协程的launch()和async()的区别
  3. Kotlin 作用域函数(let、run、with、apply、also)的使用指南
  4. Android 详解:高频使用的 8 种设计模式的核心思想和代码实现
  5. 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
  6. Android ContentProvider 详解及结合 Jetpack Startup 的优化实践
相关推荐
aykon2 小时前
SparseArray详解,SparseArray和HashMap性能、内存对比
app
Kapaseker4 小时前
2026年,我们还该不该学编程?
android·kotlin
Kapaseker1 天前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
BoomHe2 天前
Now in Android 架构模式全面分析
android·android jetpack
Kapaseker2 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
FunnySaltyFish3 天前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker3 天前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker4 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
黄林晴4 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
Haha_bj6 天前
Flutter——状态管理 Provider 详解
flutter·app