温馨提示:本文最后更新于
2025-12-18 14:17:47,某些文章具有时效性,若有错误或已失效,请在下方留言。Room Database 是 Android 官方提供的本地数据库框架,是 Jetpack 架构组件的一部分,用于在应用中以安全、简洁、高效的方式存储本地数据。它在 SQLite 之上提供了更高层的抽象,让开发者更容易读写数据库,并减少样板代码。
核心概念
Room Database 有三个主要的核心概念
- Entity
- DAO(Database Access Object)
- Database
Entity 实体
- 对应数据库中的一张表
- 每个字段对应表中的一列
- 使用
@Entity注解定义
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
public int uid;
public String name;
public int age;
}
DAO 数据库访问对象
- 定义访问数据库的方法(增删改查)
Room会根据DAO自动生成实际SQL代码- 使用
@Dao注解
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
@Dao
public interface UserDao {
@Query("SELECT * FROM User")
List<User> getAll();
@Insert
void insert(User user);
@Delete
void delete(User user);
}
Database 数据库定义
- 继承
RoomDatabase - 使用
@Database注解 - 将所有
Entity与DAO注册进去
import androidx.room.Database;
import androidx.room.RoomDatabase;
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
基本使用
1. 添加依赖
在 bundle.gradle.kts 文件中,添加 ROOM 相关的依赖。
// build.gradle.kts 文件
plugins {
...
alias(libs.plugins.ksp)
}
dependencies {
...
// Room DB
implementation(libs.androidx.room.runtime)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.room.ktx)
}
# libs.version.toml 文件
[versions]
...
kotlin = "2.2.0"
roomRuntime = "2.8.4"
[libraries]
...
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
[plugins]
...
# ksp 版本要与 kotlin 版本一致
ksp = { id = "com.google.devtools.ksp", version = "2.2.0-2.0.2" }
// build.gradle.kts 文件
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
...
alias(libs.plugins.ksp) apply false
}
添加完成后,点击 Sync Now 按钮,开始同步配置。
2. 创建 Entity 实体
Entity 是表示 SQLite 数据库中的表的基本组件。新建 Contacts 实体,实体包含 id、name 以及 email。
package com.stewednoodles.contactsmanagerapp;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
/**
* 实体类
* @Entity: 将 tableName 与实体类 Movie 进行映射
*/
@Entity(tableName = "movies_table")
data class Movie(
@PrimaryKey
val id: Int,
val title: String,
val overview: String,
@ColumnInfo(name = "poster_path")
val movieImg: String
)
3. 创建 DAO
DAO 是一个接口,定义了一系列用于对 Entity 数据库表执行数据库操作的方法,例如 inset、update、delete、query 以及其他操作。
DAO 是一个用 @Dao 注解的接口。
@Dao
interface MovieDAO {
@Insert
suspend fun insert(movie: Movie)
@Insert
suspend fun insetMovieList(movies: List<Movie>)
@Query("SELECT * FROM movies_table")
suspend fun getAllMoviesInDB(): List<Movie>
}
4. 创建 Database 类
Database 类是一个抽象类,用作数据库的持有者。
/**
* 定义了数据库中的实体(表)和版本号
* - 数据库变更时,可以更新版本号
*/
@Database(entities = [Movie::class], version = 1)
abstract class MovieDB : RoomDatabase() {
// DAO
abstract val movieDAO: MovieDAO
companion object {
// Volatile在多线程中避免条件竞争
@Volatile
private var INSTANCE: MovieDB? = null
fun getInstance(context: Context): MovieDB {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context = context.applicationContext,
klass = MovieDB::class.java,
name = "movies_db"
).build()
}
INSTANCE = instance
return instance
}
}
}
}
5. 创建 Repository
Repository 可以从不同的数据源(不同的 REST API、缓存、本地数据库存储)收集数据,并将这些数据提供给应用程序的其余部分。有效递将数据源与应用程序的其他部分隔离开来,并为应用程序的其余部分提供一个干净的数据访问 API。
DAO 中的方法从 Repository 执行。
class Repository(context: Context) {
// 从网络获取数据
suspend fun getPopularMoviesFromOnline(apiKey: String): List<Movie> {
return RetrofitInstance.api.getPopularMovies(apiKey).results
}
// 从数据库中获取数据
private val db = MovieDB.getInstance(context)
private val movieDAO: MovieDAO = db.movieDAO
suspend fun getMoviesFromDB(): List<Movie> {
return movieDAO.getAllMoviesInDB()
}
suspend fun insertMoviesIntoDB(movies: List<Movie>) {
movieDAO.insetMovieList(movies)
}
suspend fun insertMovieIntoDB(movie: Movie) {
movieDAO.insert(movie)
}
}
6. ViewModel
class MovieViewModel(repository: Repository) : ViewModel() {
// ViewModel 使用 mutableStateOf<> 而不是 LiveData
// 从而直接由 Compose 进行状态管理
//
// 当 'movies' 的值发生变化时,Compose 会自动
// 重新组合(recompose)所有依赖该状态的 UI 部分
var movies by mutableStateOf<List<Movie>>(emptyList())
private set
// 从网络中获取
var moviesFromApi by mutableStateOf<List<Movie>>(emptyList())
private set
// 从本地数据库中获取
var moviesFromRoomDB by mutableStateOf<List<Movie>>(emptyList())
private set
init {
viewModelScope.launch {
try {
// 从网络抓取数据
moviesFromApi = repository.getPopularMoviesFromOnline("172dc15a2a4598f149f4d87f13bbbc59")
// 数据存入数据库
repository.insertMoviesIntoDB(moviesFromApi)
// 赋值
movies = moviesFromApi
} catch (e: Exception) {
// 从数据库获取影视数据
moviesFromRoomDB = repository.getMoviesFromDB()
movies = moviesFromRoomDB
}
}
}
}
© 版权声明
THE END













暂无评论内容