Android Room用法详解

Room 是 Android 官方推荐的数据库框架,它是 SQLite 的抽象封装,提供了更便捷的数据库操作方式,支持 Kotlin 协程和 LiveData。以下是 Room 的基本使用方法:


1. 添加 Room 依赖

在 build.gradle.kts(模块级)中添加 Room 相关依赖:

kotlin 复制代码
dependencies {
    val room_version = "2.6.1" // 确保使用最新版本
​
    implementation("androidx.room:room-runtime:$room_version")
    kapt("androidx.room:room-compiler:$room_version") // 用于注解处理器
​
    implementation("androidx.room:room-ktx:$room_version") // 支持 Kotlin 协程
}

如果项目使用 Kotlin Symbol Processing (KSP) 代替 kapt:

bash 复制代码
ksp("androidx.room:room-compiler:$room_version")

2. 创建数据库实体(Entity)

使用 @Entity 注解定义数据库表:

kotlin 复制代码
import androidx.room.Entity
import androidx.room.PrimaryKey
​
@Entity(tableName = "diary_entries") // 指定表名
data class DiaryEntry(
    @PrimaryKey(autoGenerate = true) val id: Int = 0, // 主键,自动生成
    val title: String,
    val content: String,
    val date: Long, // 以时间戳形式存储日期
    val weather: String? = null
)

3. 创建 DAO(数据访问对象)

DAO 负责数据库的 CRUD 操作:

less 复制代码
import androidx.room.*
​
@Dao
interface DiaryDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertDiary(entry: DiaryEntry)
​
    @Update
    suspend fun updateDiary(entry: DiaryEntry)
​
    @Delete
    suspend fun deleteDiary(entry: DiaryEntry)
​
    @Query("SELECT * FROM diary_entries ORDER BY date DESC")
    fun getAllDiaries(): List<DiaryEntry> // 直接返回列表(不推荐,建议使用 Flow)
​
    @Query("SELECT * FROM diary_entries WHERE id = :id")
    suspend fun getDiaryById(id: Int): DiaryEntry?
​
    @Query("SELECT * FROM diary_entries WHERE title LIKE '%' || :query || '%'")
    fun searchDiaries(query: String): List<DiaryEntry>
}

如果需要监听数据变化,可以用 Flow:

kotlin 复制代码
@Query("SELECT * FROM diary_entries ORDER BY date DESC")
fun getAllDiariesFlow(): Flow<List<DiaryEntry>> // 使用 Flow 以支持实时监听

4. 创建数据库(Database)

使用 @Database 注解创建 Room 数据库:

kotlin 复制代码
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
​
@Database(entities = [DiaryEntry::class], version = 1, exportSchema = false)
abstract class DiaryDatabase : RoomDatabase() {
    abstract fun diaryDao(): DiaryDao
​
    companion object {
        @Volatile
        private var INSTANCE: DiaryDatabase? = null
​
        fun getDatabase(context: Context): DiaryDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    DiaryDatabase::class.java,
                    "diary_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

说明:

  • @Volatile 确保多个线程能正确访问 INSTANCE。
  • synchronized(this) 确保数据库实例的单例模式。

5. 在 ViewModel 中使用

在 ViewModel 里封装数据库操作:

kotlin 复制代码
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.Flow
​
class DiaryViewModel(private val diaryDao: DiaryDao) : ViewModel() {
    val allDiaries: Flow<List<DiaryEntry>> = diaryDao.getAllDiariesFlow()
​
    suspend fun addDiary(entry: DiaryEntry) {
        diaryDao.insertDiary(entry)
    }
​
    suspend fun deleteDiary(entry: DiaryEntry) {
        diaryDao.deleteDiary(entry)
    }
}

在 viewmodel 目录下新建 DiaryViewModelFactory.kt 文件,并写入以下代码:

kotlin 复制代码
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.uibestpractice.data.DiaryDao // 替换为你的包名
​
class DiaryViewModelFactory(private val diaryDao: DiaryDao) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(DiaryViewModel::class.java)) {
            return DiaryViewModel(diaryDao) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }

6. 在 Activity/Fragment 中使用

在 Activity 或 Fragment 里使用 ViewModel:

kotlin 复制代码
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
​
class MainActivity : AppCompatActivity() {
    private val diaryViewModel: DiaryViewModel by viewModels {
        DiaryViewModelFactory(DiaryDatabase.getDatabase(this).diaryDao())
    }
​
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
​
        // 监听数据库变化
        lifecycleScope.launch {
            diaryViewModel.allDiaries.collect { diaryList ->
                // 更新 UI
            }
        }
    }
​
    private fun addDiaryEntry() {
        lifecycleScope.launch {
            val newEntry = DiaryEntry(title = "新日记", content = "今天很开心!", date = System.currentTimeMillis())
            diaryViewModel.addDiary(newEntry)
        }
    }
}

7. 线程调度(协程)

Room 允许在 suspend 函数中调用数据库操作,Kotlin 协程会自动切换到 IO 线程:

kotlin 复制代码
suspend fun insertDiary(entry: DiaryEntry) {
    diaryDao.insertDiary(entry) // Room 在 IO 线程执行
}

对于 不支持协程的函数 (如 getAllDiaries()),应使用 withContext(Dispatchers.IO):

kotlin 复制代码
fun getAllDiariesBlocking(): List<DiaryEntry> {
    return runBlocking { withContext(Dispatchers.IO) { diaryDao.getAllDiaries() } }
}

总结

Room 提供了 简单、安全、高效 的数据库管理:

  1. Entity (表) → @Entity
  2. DAO (数据操作) → @Dao
  3. Database (数据库实例) → @Database
  4. ViewModel(封装业务逻辑)
  5. Activity/Fragment(UI 层使用数据库)

你可以结合 Flow 进行 实时监听 ,结合 Kotlin 协程 进行 异步处理,使数据库操作更加流畅高效。

相关推荐
啾咪orJIUMI1 小时前
Vue 3 + 高德地图封装实战:点位、区域、Loca 流光与 Vue 信息窗体
前端·vue.js
掘金者阿豪1 小时前
AI数据库不只是向量检索:从数据语义到库内智能计算的技术演进
前端
梦里寻码2 小时前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
FRing032 小时前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
SameX2 小时前
HarmonyOS ArkUI Dialog 复用 用 @CustomDialog + enum type 做多类型统一管理的做法
前端
AiMan2 小时前
豆包爱学还是不可以导出左侧所有对话,只能单容导出,方法不对吗
前端
AiMan2 小时前
Grok生成的内容能否下载吗?
前端
徐小夕3 小时前
JitArchives,一款基于JitWord协同AI文档打造的企业级电子档案系统
前端·vue.js·github
陈随易3 小时前
Node.js 2026上半年都有哪些性能提升?
前端·后端·程序员
墨林陌3 小时前
AI 热点日报(2026-11-09):苹果代理式Siri曝光,Anthropic推进IPO,编码智能体实测翻车
前端