Android Room数据库使用先容

打印 上一主题 下一主题

主题 1009|帖子 1009|积分 3037

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1.简介


Room是Google提供的Android架构组件之一,旨在简化数据库操作。它是SQLite的一个抽象层,提供了更易用和安全的API。
Room的总体架构:

2.Room数据库的基础概念


Entity

Entity是Room中的数据表,每个Entity类对应一个SQLite表。
DAO (Data Access Object)

DAO是用于访问数据库的方法接口,定义了与数据库交互的操作。
Database

Database是Room数据库的抽象类,持有数据库并作为数据访问的主要入口点。
3.Room数据库的配置


添加依靠

在build.gradle文件中添加Room的依靠项。
  1. dependencies {
  2.     implementation "androidx.room:room-runtime:2.5.0"
  3.     annotationProcessor "androidx.room:room-compiler:2.5.0"
  4.     // 可选 - 支持Lifecycle的LiveData
  5.     implementation "androidx.room:room-ktx:2.5.0"
  6. }
复制代码
定义Entity

  1. // tableName 指定了数据库中对应的表名为 "users"。如果不指定,默认使用类名作为表名
  2. @Entity(tableName = "users")
  3. data class User(
  4.     // 使用默认值 0,autoGenerate = true 表示自动生成主键
  5.     @PrimaryKey(autoGenerate = true)
  6.     val id: Int = 0,
  7.     // 如果不使用 @ColumnInfo 注解,默认情况下 Room 将使用属性名作为数据库中的列名
  8.     @ColumnInfo(name = "first_name")
  9.     val firstName: String,
  10.     @ColumnInfo(name = "last_name")
  11.     val lastName: String
  12. )
复制代码
创建DAO

  1. @Dao
  2. interface UserDao {
  3.     @Insert
  4.     fun insert(user: User)
  5.     //@Insert(onConflict = OnConflictStrategy.REPLACE):用于定义插入操作,并指定了替换策略为 OnConflictStrategy.REPLACE。这意味着如果插入的数据在数据库中已存在(根据主键判断),则旧数据会被新数据替换。
  6.     @Insert(onConflict = OnConflictStrategy.REPLACE)
  7.     fun insert(user: User)
  8.     @Query("SELECT * FROM users WHERE id = :id")
  9.     fun getUserById(id: Int): User?
  10.     @Update
  11.     fun update(user: User)
  12.     @Delete
  13.     fun delete(user: User)
  14. }
复制代码
tips: OnConflictStrategy.REPLACE:如果插入的数据在数据库中已存在(即主键辩论),则会替换原有的数据。
创建Database

  1. @Database(entities = [User::class], version = 1, exportSchema = false)
  2. abstract class UserRoomDatabase : RoomDatabase() {
  3.     abstract fun userDao(): UserDao
  4.     companion object {
  5.         @Volatile
  6.         private var INSTANCE: ItemRoomDatabase? = null
  7.         fun getDatabase(context: Context): UserRoomDatabase {
  8.             return INSTANCE ?: synchronized(this) {
  9.                 val instance = Room.databaseBuilder(
  10.                     context.applicationContext,
  11.                     UserRoomDatabase::class.java,
  12.                     "user_database"
  13.                 )
  14.                     .fallbackToDestructiveMigration()
  15.                     .build()
  16.                 INSTANCE = instance
  17.                 instance
  18.             }
  19.         }
  20.     }
  21. }
复制代码
tips:注意fallbackToDestructiveMigration() 一样平常在调试中使用,如果你修改了数据库表布局,而没有升级数据库通常程序再次运行会报错,使用fallbackToDestructiveMigration() 表示将老的数据库表布局和数据全部删除,使用新的布局,答应破坏性迁移,即烧毁旧数据库并创建新数据库。
初始化数据库

  1. val db: UserRoomDatabase by lazy { UserRoomDatabase.getDatabase(this) }
复制代码
4.Room数据库的使用


插入数据

  1. val user = User().apply {
  2.     firstName = "John"
  3.     lastName = "Doe"
  4. }
  5. db.userDao().insert(user)
复制代码
查询数据

  1. val user = db.userDao().getUserById(1)
复制代码
更新数据

  1. user.lastName = "Smith"
  2. db.userDao().update(user)
复制代码
删除数据

  1. db.userDao().delete(user)
复制代码
5.Room数据库的高级特性


使用LiveData和Flow

  1. @Query("SELECT * FROM users")
  2. LiveData<List<User>> getAllUsers();
  3. @Query("SELECT * FROM users")
  4. Flow<List<User>> getAllUsersFlow();
复制代码
数据库迁移

  1. @Database(entities = [User::class], version = 2, exportSchema = false)
  2. abstract class UserRoomDatabase : RoomDatabase() {
  3.     abstract fun userDao(): UserDao
  4.     companion object {
  5.         @Volatile
  6.         private var INSTANCE: ItemRoomDatabase? = null
  7.         //迁移代码 用于从版本 1 迁移到版本 2。
  8.         val MIGRATION_1_2: Migration = object : Migration(1, 2) {
  9.             override fun migrate(database: SupportSQLiteDatabase) {
  10.                 //为users表增加age属性
  11.                 database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER")
  12.             }
  13.         }
  14.         fun getDatabase(context: Context): UserRoomDatabase {
  15.             return INSTANCE ?: synchronized(this) {
  16.                 val instance = Room.databaseBuilder(
  17.                     context.applicationContext,
  18.                     UserRoomDatabase::class.java,
  19.                     "user_database"
  20.                 )
  21.                     .addMigrations(AppDatabase.MIGRATION_1_2) //在此处添加
  22.                     .build()
  23.                 INSTANCE = instance
  24.                 instance
  25.             }
  26.         }
  27.     }
  28. }
复制代码
使用TypeConverters

  1. @Database(entities = [User::class], version = 1)
  2. @TypeConverters(Converters::class)
  3. abstract class UserRoomDatabase: RoomDatabase() {
  4.     abstract fun userDao(): UserDao
  5.     ...
  6. }
  7. object Converters {
  8.     @TypeConverter
  9.     @JvmStatic
  10.     fun fromTimestamp(value: Long?): Date? {
  11.         return value?.let { Date(it) }
  12.     }
  13.     @TypeConverter
  14.     @JvmStatic
  15.     fun dateToTimestamp(date: Date?): Long? {
  16.         return date?.time
  17.     }
  18. }
复制代码
User 中增长 Date范例 createdAt属性
  1. @Entity(tableName = "users")
  2. data class User(
  3.     @PrimaryKey(autoGenerate = true)
  4.     val id: Long = 0,
  5.     val name: String,
  6.     val createdAt: Date
  7. )
复制代码
说明:


  • 范例转换器 (Converters):使用 Room 持久化库时,有时需要在数据库存储和应用程序中的对象之间进行转换。例如,将 Date 对象存储为 Long 范例的时间戳或从时间戳规复为 Date 对象,其他对象范例同理。
  • @TypeConverter 注解:用于标记范例转换器的方法,告诉 Room 如安在持久化过程中实验对象到数据库兼容格式之间的转换。
  • @Database 和 @TypeConverters 注解:用于在 UserRoomDatabase中指定命据库的配置,包括数据库版本号和要使用的范例转换器。
示例:
  1. class Converters {
  2.     //enum 类型
  3.     @TypeConverter
  4.     fun toDownloadStatus(value: String): DownloadStatus = enumValueOf(value)
  5.     @TypeConverter
  6.     fun fromDownloadStatus(status: DownloadStatus): String = status.name
  7.     @TypeConverter
  8.     fun fromHashMap(value: HashMap<Int, Int>): String {
  9.         val gson = Gson()
  10.         return gson.toJson(value)
  11.     }
  12.     @TypeConverter
  13.     fun toHashMap(value: String): HashMap<Int, Int> {
  14.         val gson = Gson()
  15.         val type = object : TypeToken<HashMap<Int, Int>>() {}.type
  16.         return gson.fromJson(value, type)
  17.     }
  18.     //自定义对象
  19.     @TypeConverter
  20.     fun fromDownloadException(downloadException: DownloadException?): String? {
  21.         if (downloadException == null) {
  22.             return null
  23.         }
  24.         return Gson().toJson(downloadException)
  25.     }
  26.     @TypeConverter
  27.     fun toDownloadException(value: String?): DownloadException? {
  28.         if (value == null) {
  29.             return null
  30.         }
  31.         val type = object : TypeToken<DownloadException>() {}.type
  32.         return Gson().fromJson(value, type)
  33.     }
  34. }
复制代码
6. Room数据库的实践


线程管理

确保数据库操作在后台线程中完成,在主线程中操作数据库会报错。
  1. Executors.newSingleThreadExecutor().execute {
  2.     db.userDao().insert(user)
  3. }
复制代码
数据库性能优化



  • 使用批量插入和更新。
  • 使用索引进步查询性能。
处理大型数据集

使用分页库(Paging Library)处理大型数据集。
  1. @Query("SELECT * FROM users ORDER BY id ASC")
  2. fun getAllUsers(): PagingSource<Int, User>
复制代码
使用分页库需要增长依靠
  1. implementation "androidx.paging:paging-runtime-ktx:$paging_version"
复制代码

后面单独写篇文章先容分页库使用,敬请期待…

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

篮之新喜

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表