Room 是 Android 官方推荐的数据库框架,它是 SQLite 的抽象封装,提供了更便捷的数据库操作方式,支持 Kotlin 协程和 LiveData。以下是 Room 的基本使用方法:
1. 添加 Room 依赖 在 build.gradle.kts
(模块级)中添加 Room 相关依赖:
1 2 3 4 5 6 7 8 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:
1 ksp("androidx.room:room-compiler:$room_version")
2. 创建数据库实体(Entity) 使用 @Entity
注解定义数据库表:
1 2 3 4 5 6 7 8 9 10 11 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 操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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
:
1 2 @Query("SELECT * FROM diary_entries ORDER BY date DESC") fun getAllDiariesFlow(): Flow<List<DiaryEntry>> // 使用 Flow 以支持实时监听
4. 创建数据库(Database) 使用 @Database
注解创建 Room 数据库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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
里封装数据库操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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
文件,并写入以下代码:
1 2 3 4 5 6 7 8 9 10 11 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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 线程:
1 2 3 suspend fun insertDiary(entry: DiaryEntry) { diaryDao.insertDiary(entry) // Room 在 IO 线程执行 }
对于 不支持协程的函数 (如 getAllDiaries()
),应使用 withContext(Dispatchers.IO)
:
1 2 3 fun getAllDiariesBlocking(): List<DiaryEntry> { return runBlocking { withContext(Dispatchers.IO) { diaryDao.getAllDiaries() } } }
总结 Room 提供了 简单、安全、高效 的数据库管理:
Entity (表) → @Entity
DAO (数据操作) → @Dao
Database (数据库实例) → @Database
ViewModel (封装业务逻辑)
Activity/Fragment (UI 层使用数据库)
你可以结合 Flow
进行 实时监听 ,结合 Kotlin 协程 进行 异步处理 ,使数据库操作更加流畅高效。