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 协程 进行 异步处理,使数据库操作更加流畅高效。

相关推荐
Qlly10 分钟前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝14 分钟前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦14 分钟前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡35 分钟前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI41 分钟前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95271 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人1 小时前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载1 小时前
用表格模拟甘特图:项目排期的土办法
前端·低代码
葡萄城技术团队1 小时前
用 SpreadJS 数据验证实现省市区三级联动
前端
派小心.2 小时前
A/B实验分层随机种子的稳定性验证
大数据·服务器·前端·数据分析