马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
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的依靠项。
- dependencies {
- implementation "androidx.room:room-runtime:2.5.0"
- annotationProcessor "androidx.room:room-compiler:2.5.0"
- // 可选 - 支持Lifecycle的LiveData
- implementation "androidx.room:room-ktx:2.5.0"
- }
复制代码 定义Entity
- // tableName 指定了数据库中对应的表名为 "users"。如果不指定,默认使用类名作为表名
- @Entity(tableName = "users")
- data class User(
- // 使用默认值 0,autoGenerate = true 表示自动生成主键
- @PrimaryKey(autoGenerate = true)
- val id: Int = 0,
- // 如果不使用 @ColumnInfo 注解,默认情况下 Room 将使用属性名作为数据库中的列名
- @ColumnInfo(name = "first_name")
- val firstName: String,
- @ColumnInfo(name = "last_name")
- val lastName: String
- )
复制代码 创建DAO
- @Dao
- interface UserDao {
- @Insert
- fun insert(user: User)
- //@Insert(onConflict = OnConflictStrategy.REPLACE):用于定义插入操作,并指定了替换策略为 OnConflictStrategy.REPLACE。这意味着如果插入的数据在数据库中已存在(根据主键判断),则旧数据会被新数据替换。
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- fun insert(user: User)
- @Query("SELECT * FROM users WHERE id = :id")
- fun getUserById(id: Int): User?
- @Update
- fun update(user: User)
- @Delete
- fun delete(user: User)
- }
复制代码 tips: OnConflictStrategy.REPLACE:如果插入的数据在数据库中已存在(即主键辩论),则会替换原有的数据。
创建Database
- @Database(entities = [User::class], version = 1, exportSchema = false)
- abstract class UserRoomDatabase : RoomDatabase() {
- abstract fun userDao(): UserDao
- companion object {
- @Volatile
- private var INSTANCE: ItemRoomDatabase? = null
- fun getDatabase(context: Context): UserRoomDatabase {
- return INSTANCE ?: synchronized(this) {
- val instance = Room.databaseBuilder(
- context.applicationContext,
- UserRoomDatabase::class.java,
- "user_database"
- )
- .fallbackToDestructiveMigration()
- .build()
- INSTANCE = instance
- instance
- }
- }
- }
- }
复制代码 tips:注意fallbackToDestructiveMigration() 一样平常在调试中使用,如果你修改了数据库表布局,而没有升级数据库通常程序再次运行会报错,使用fallbackToDestructiveMigration() 表示将老的数据库表布局和数据全部删除,使用新的布局,答应破坏性迁移,即烧毁旧数据库并创建新数据库。
初始化数据库
- val db: UserRoomDatabase by lazy { UserRoomDatabase.getDatabase(this) }
复制代码 4.Room数据库的使用
插入数据
- val user = User().apply {
- firstName = "John"
- lastName = "Doe"
- }
- db.userDao().insert(user)
复制代码 查询数据
- val user = db.userDao().getUserById(1)
复制代码 更新数据
- user.lastName = "Smith"
- db.userDao().update(user)
复制代码 删除数据
- db.userDao().delete(user)
复制代码 5.Room数据库的高级特性
使用LiveData和Flow
- @Query("SELECT * FROM users")
- LiveData<List<User>> getAllUsers();
- @Query("SELECT * FROM users")
- Flow<List<User>> getAllUsersFlow();
复制代码 数据库迁移
- @Database(entities = [User::class], version = 2, exportSchema = false)
- abstract class UserRoomDatabase : RoomDatabase() {
- abstract fun userDao(): UserDao
- companion object {
- @Volatile
- private var INSTANCE: ItemRoomDatabase? = null
- //迁移代码 用于从版本 1 迁移到版本 2。
- val MIGRATION_1_2: Migration = object : Migration(1, 2) {
- override fun migrate(database: SupportSQLiteDatabase) {
- //为users表增加age属性
- database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER")
- }
- }
- fun getDatabase(context: Context): UserRoomDatabase {
- return INSTANCE ?: synchronized(this) {
- val instance = Room.databaseBuilder(
- context.applicationContext,
- UserRoomDatabase::class.java,
- "user_database"
- )
- .addMigrations(AppDatabase.MIGRATION_1_2) //在此处添加
- .build()
- INSTANCE = instance
- instance
- }
- }
- }
- }
复制代码 使用TypeConverters
- @Database(entities = [User::class], version = 1)
- @TypeConverters(Converters::class)
- abstract class UserRoomDatabase: RoomDatabase() {
- abstract fun userDao(): UserDao
- ...
- }
- object Converters {
- @TypeConverter
- @JvmStatic
- fun fromTimestamp(value: Long?): Date? {
- return value?.let { Date(it) }
- }
- @TypeConverter
- @JvmStatic
- fun dateToTimestamp(date: Date?): Long? {
- return date?.time
- }
- }
复制代码 User 中增长 Date范例 createdAt属性
- @Entity(tableName = "users")
- data class User(
- @PrimaryKey(autoGenerate = true)
- val id: Long = 0,
- val name: String,
- val createdAt: Date
- )
复制代码 说明:
- 范例转换器 (Converters):使用 Room 持久化库时,有时需要在数据库存储和应用程序中的对象之间进行转换。例如,将 Date 对象存储为 Long 范例的时间戳或从时间戳规复为 Date 对象,其他对象范例同理。
- @TypeConverter 注解:用于标记范例转换器的方法,告诉 Room 如安在持久化过程中实验对象到数据库兼容格式之间的转换。
- @Database 和 @TypeConverters 注解:用于在 UserRoomDatabase中指定命据库的配置,包括数据库版本号和要使用的范例转换器。
示例:
- class Converters {
- //enum 类型
- @TypeConverter
- fun toDownloadStatus(value: String): DownloadStatus = enumValueOf(value)
- @TypeConverter
- fun fromDownloadStatus(status: DownloadStatus): String = status.name
- @TypeConverter
- fun fromHashMap(value: HashMap<Int, Int>): String {
- val gson = Gson()
- return gson.toJson(value)
- }
- @TypeConverter
- fun toHashMap(value: String): HashMap<Int, Int> {
- val gson = Gson()
- val type = object : TypeToken<HashMap<Int, Int>>() {}.type
- return gson.fromJson(value, type)
- }
- //自定义对象
- @TypeConverter
- fun fromDownloadException(downloadException: DownloadException?): String? {
- if (downloadException == null) {
- return null
- }
- return Gson().toJson(downloadException)
- }
- @TypeConverter
- fun toDownloadException(value: String?): DownloadException? {
- if (value == null) {
- return null
- }
- val type = object : TypeToken<DownloadException>() {}.type
- return Gson().fromJson(value, type)
- }
- }
复制代码 6. Room数据库的实践
线程管理
确保数据库操作在后台线程中完成,在主线程中操作数据库会报错。
- Executors.newSingleThreadExecutor().execute {
- db.userDao().insert(user)
- }
复制代码 数据库性能优化
处理大型数据集
使用分页库(Paging Library)处理大型数据集。
- @Query("SELECT * FROM users ORDER BY id ASC")
- fun getAllUsers(): PagingSource<Int, User>
复制代码 使用分页库需要增长依靠
- implementation "androidx.paging:paging-runtime-ktx:$paging_version"
复制代码 …
后面单独写篇文章先容分页库使用,敬请期待…
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |