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 进行数据持久化操作,实现应用数据的存储和查询。

相关推荐
没有了遇见41 分钟前
Kotlin高级用法之<扩展函数/属性>
android·kotlin
安卓开发者43 分钟前
Android中使用RxJava实现网络请求与缓存策略
android·网络·rxjava
AI 嗯啦1 小时前
SQL详细语法教程(七)核心优化
数据库·人工智能·sql
2501_915921432 小时前
iOS 应用上架多环境实战,Windows、Linux 与 Mac 的不同路径
android·ios·小程序·https·uni-app·iphone·webview
ClouGence2 小时前
三步搞定!GaussDB 实时数据入仓
数据库·后端
wstcl3 小时前
安卓app、微信小程序等访问多个api时等待提示调用与关闭问题
android·微信小程序·webapi
鼠鼠我捏,要死了捏3 小时前
生产环境MongoDB分片策略优化与故障排查实战经验分享
数据库·mongodb·分片
KaiwuDB4 小时前
KWDB 分布式架构探究——数据分布与特性
数据库·分布式
笨蛋不要掉眼泪4 小时前
Spring Boot集成腾讯云人脸识别实现智能小区门禁系统
java·数据库·spring boot
louisgeek5 小时前
Android Studio 打印中文乱码
android