Android开发实战班 - 数据持久化 - Room 数据库应用

在 Android 应用开发中,数据持久化是实现用户数据保存、应用状态保存等功能的重要手段。Room 是 Google 推出的一个基于 SQLite 的持久化库,提供了更简洁、安全和强大的数据库操作接口。Room 抽象了 SQLite 数据库的使用,简化了数据库操作,并提供了编译时 SQL 语句检查等功能。本章节将介绍 Room 数据库的基本概念、架构、常用注解以及在 Android 项目中的应用,帮助学员掌握 Room 数据库的使用。

15.1 Room 简介

  • Room 的历史与发展:

    • Room 是 Google 在 2017 年推出的持久化库,旨在简化 Android 应用中的 SQLite 数据库操作。
    • Room 提供了更简洁的 API,编译时 SQL 语句检查,以及与 LiveData 和 Flow 的无缝集成。
  • Room 的优势:

    • 简洁易用: 相比直接使用 SQLite,Room 提供了更简洁的 API,简化了数据库操作。
    • 编译时检查: Room 在编译时会检查 SQL 语句的正确性,避免运行时错误。
    • 与 LiveData 和 Flow 集成: Room 支持与 LiveData 和 Flow 集成,可以方便地观察数据库数据的变化。
    • 支持注解: Room 使用注解来定义实体、DAO 和数据库,代码更简洁易读。
    • 线程安全: Room 默认在后台线程中执行数据库操作,避免阻塞主线程。

15.2 Room 架构

Room 主要由三个组件组成:

  1. Entity(实体):

    • 实体类表示数据库中的表。
    • 使用 @Entity 注解定义实体类,并使用 @PrimaryKey, @ColumnInfo 等注解定义表结构和字段。
    kotlin 复制代码
    @Entity(tableName = "users")
    data class User(
        @PrimaryKey(autoGenerate = true) val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?
    )
  2. DAO(数据访问对象):

    • DAO 类用于定义数据库操作,例如查询、插入、更新、删除等。
    • 使用 @Dao 注解定义 DAO 接口,并使用 @Query, @Insert, @Update, @Delete 等注解定义数据库操作方法。
    kotlin 复制代码
    @Dao
    interface UserDao {
        @Query("SELECT * FROM users")
        fun getAllUsers(): LiveData<List<User>>
    
        @Query("SELECT * FROM users WHERE id = :id")
        fun getUserById(id: Int): User
    
        @Insert
        suspend fun insertUser(user: User)
    
        @Update
        suspend fun updateUser(user: User)
    
        @Delete
        suspend fun deleteUser(user: User)
    }
  3. Database(数据库):

    • Database 类是 Room 数据库的入口,用于获取 DAO 实例。
    • 使用 @Database 注解定义 Database 类,并指定实体类和版本号。
    kotlin 复制代码
    @Database(entities = [User::class], version = 1)
    abstract class AppDatabase : RoomDatabase() {
        abstract fun userDao(): UserDao
    
        companion object {
            @Volatile
            private var INSTANCE: AppDatabase? = null
    
            fun getDatabase(context: Context): AppDatabase {
                return INSTANCE ?: synchronized(this) {
                    val instance = Room.databaseBuilder(
                        context.applicationContext,
                        AppDatabase::class.java,
                        "app_database"
                    ).build()
                    INSTANCE = instance
                    instance
                }
            }
        }
    }

15.3 Room 常用注解

  • @Entity:

    • 定义实体类,表示数据库中的表。
    • 可以使用 tableName 属性指定表名。
    • 可以使用 primaryKeys, foreignKeys, indices 等属性定义表的主键、外键和索引。
    kotlin 复制代码
    @Entity(tableName = "users")
    data class User(
        @PrimaryKey(autoGenerate = true) val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?
    )
  • @Dao:

    • 定义 DAO 接口,用于定义数据库操作。
    • 可以使用 @Query, @Insert, @Update, @Delete 等注解定义数据库操作方法。
    kotlin 复制代码
    @Dao
    interface UserDao {
        @Query("SELECT * FROM users")
        fun getAllUsers(): LiveData<List<User>>
    
        @Insert
        suspend fun insertUser(user: User)
    
        @Update
        suspend fun updateUser(user: User)
    
        @Delete
        suspend fun deleteUser(user: User)
    }
  • @Database:

    • 定义 Database 类,表示 Room 数据库。
    • 需要指定实体类和版本号。
    kotlin 复制代码
    @Database(entities = [User::class], version = 1)
    abstract class AppDatabase : RoomDatabase() {
        abstract fun userDao(): UserDao
    }
  • @ColumnInfo:

    • 定义实体类字段对应的数据库列。
    • 可以使用 name 属性指定列名。
    kotlin 复制代码
    @ColumnInfo(name = "first_name")
    val firstName: String?
  • @PrimaryKey:

    • 定义实体类的主键。
    • 可以使用 autoGenerate 属性指定主键是否自动生成。
    kotlin 复制代码
    @PrimaryKey(autoGenerate = true)
    val id: Int
  • @Ignore:

    • 忽略实体类中的字段,不将其映射到数据库表中。
    kotlin 复制代码
    @Ignore
    val tempData: String?

15.4 Room 常用操作

  • 插入数据:

    kotlin 复制代码
    @Insert
    suspend fun insertUser(user: User)
  • 查询数据:

    kotlin 复制代码
    @Query("SELECT * FROM users")
    fun getAllUsers(): LiveData<List<User>>
    
    @Query("SELECT * FROM users WHERE id = :id")
    fun getUserById(id: Int): User
  • 更新数据:

    kotlin 复制代码
    @Update
    suspend fun updateUser(user: User)
  • 删除数据:

    kotlin 复制代码
    @Delete
    suspend fun deleteUser(user: User)
  • 事务操作:

    kotlin 复制代码
    @Transaction
    suspend fun insertOrUpdateUser(user: User) {
        val existingUser = getUserById(user.id)
        if (existingUser != null) {
            updateUser(user)
        } else {
            insertUser(user)
        }
    }

15.5 Room 与 LiveData 和 Flow

Room 支持与 LiveData 和 Flow 集成,可以方便地观察数据库数据的变化。

  • 与 LiveData 集成:

    kotlin 复制代码
    @Query("SELECT * FROM users")
    fun getAllUsers(): LiveData<List<User>>
    kotlin 复制代码
    class MyActivity : AppCompatActivity() {
        private lateinit var viewModel: MyViewModel
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
            viewModel.users.observe(this) { users ->
                // 更新 UI
            }
    
            viewModel.loadUsers()
        }
    }
  • 与 Flow 集成:

    kotlin 复制代码
    @Query("SELECT * FROM users")
    fun getAllUsers(): Flow<List<User>>
    kotlin 复制代码
    @Composable
    fun MyComposable(viewModel: MyViewModel) {
        val users by viewModel.users.collectAsState()
    
        LazyColumn {
            items(users) { user ->
                Text(text = user.firstName)
            }
        }
    }

15.6 实战案例

  1. 案例一:使用 Room 实现用户列表应用

    • 定义 User 实体类。
    • 定义 UserDao 接口,添加查询、插入、更新、删除方法。
    • 创建 AppDatabase 类,初始化 Room 数据库。
    • 创建 ViewModel,使用 Room 进行数据库操作。
    • 在 Activity 中观察 ViewModel 的 LiveData,更新 RecyclerView。
  2. 案例二:使用 Room 实现图片浏览应用

    • 定义 Image 实体类。
    • 定义 ImageDao 接口,添加查询、插入、更新、删除方法。
    • 创建 AppDatabase 类,初始化 Room 数据库。
    • 创建 ViewModel,使用 Room 进行数据库操作。
    • 在 Jetpack Compose Composable 中观察 ViewModel 的 Flow,更新 UI。

15.7 课后作业

  1. 任务一:使用 Room 实现用户列表应用

    • 定义 User 实体类。
    • 定义 UserDao 接口,添加查询、插入、更新、删除方法。
    • 创建 AppDatabase 类,初始化 Room 数据库。
    • 创建 ViewModel,使用 Room 进行数据库操作。
    • 在 Activity 中观察 ViewModel 的 LiveData,更新 RecyclerView。
  2. 任务二:使用 Room 实现图片浏览应用

    • 定义 Image 实体类。
    • 定义 ImageDao 接口,添加查询、插入、更新、删除方法.
    • 创建 AppDatabase 类,初始化 Room 数据库.
    • 创建 ViewModel,使用 Room 进行数据库操作.
    • 在 Jetpack Compose Composable 中观察 ViewModel 的 Flow,更新 UI.
  3. 任务三:使用 Room 实现网络请求缓存

    • 定义网络请求结果实体类.
    • 定义 DAO 接口,添加插入和查询方法.
    • 创建 ViewModel,使用 Room 进行数据库操作.
    • 在 Activity 中使用协程进行网络请求,并将结果保存到数据库.
    • 在 Activity 中观察 ViewModel 的 LiveData,更新 UI.

通过本章节的学习,学员将能够掌握 Room 数据库的基本概念、架构、常用注解以及在 Android 项目中的应用,并能够使用 Room 进行数据持久化操作,实现应用数据的存储和查询。

相关推荐
广州灵眸科技有限公司12 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
憧憬成为web高手15 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
HLC++15 小时前
Linux的进程间通信
android·linux·服务器
段一凡-华北理工大学15 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
白露与泡影16 小时前
Arthas 实战指南:从方法耗时定位到 JVM 变量热修改
服务器·jvm·c#
oradh17 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
z1234567898618 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD18 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
java_logo18 小时前
Docker Compose 部署 ClickHouse:快速搭建高性能列式数据库
数据库·clickhouse·docker·列式数据库·轩辕镜像·高性能数据库·clickhouse部署教程
爱笑鱼18 小时前
Binder(二):AIDL 生成的 Proxy、Stub 和 Parcel 到底在做什么?
android