📜  Kotlin 中的 Android Room Persistence Library(1)

📅  最后修改于: 2023-12-03 14:43:41.237000             🧑  作者: Mango

Kotlin 中的 Android Room Persistence Library

Android中提供了一种操作SQLite数据库的方式,即使用Room Persistence Library。Room是Google官方推出的一种ORM(Object Relational Mapping)框架,实现了面向对象的SQLite操作方法。

优势

相比于传统的基于SQL语句的数据库操作方式,Room提供了以下优势:

  1. 更加简洁,易于理解和使用
  2. 提高了代码的可读性和可维护性
  3. 在编译时就可以发现代码中存在的错误,而非在运行时才抛出异常
  4. 减少了手动编写大量的编写SQL语句,提高了开发效率
架构

Room主要包括3个组件:Database、Entity和DAO。其中Entity作为数据库中数据表的实体类,DAO(Data Access Object)负责数据库操作,而Database作为整个数据库的抽象层。

Entity

Entity用于表示数据库中的表结构,用Kotlin中的data class进行定义,例如:

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

其中,@PrimaryKey表示该字段为主键,@ColumnInfo表示该字段在表中对应的列名。

DAO

DAO定义了数据库的操作方法,通过@Dao注解进行标记,例如:

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

其中,@Query表示查询语句,@Insert表示插入语句,@Delete表示删除语句。

Database

Database是整个Room的抽象层,提供了获取DAO实例的方法,例如:

@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

其中,@Database用于指定实体类和数据库版本号。

使用步骤
  1. 添加依赖:
    dependencies {
        def room_version = "2.3.0"
    
        implementation "androidx.room:room-runtime:$room_version"
        kapt "androidx.room:room-compiler:$room_version"
    }
    
  2. 定义实体类
    @Entity
    data class User(
        @PrimaryKey val uid: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?
    )
    
  3. 定义DAO接口
    @Dao
    interface UserDao {
        @Query("SELECT * FROM user")
        fun getAll(): List<User>
    
        @Query("SELECT * FROM user WHERE uid IN (:userIds)")
        fun loadAllByIds(userIds: IntArray): List<User>
    
        @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
               "last_name LIKE :last LIMIT 1")
        fun findByName(first: String, last: String): User
    
        @Insert
        fun insertAll(vararg users: User)
    
        @Delete
        fun delete(user: User)
    }
    
  4. 定义Database抽象类
    @Database(entities = arrayOf(User::class), version = 1)
    abstract class AppDatabase : RoomDatabase() {
        abstract fun userDao(): UserDao
    }
    
  5. 在Application类中初始化
    class MyApp :Application() {
    
         val database : AppDatabase by lazy { 
             Room.databaseBuilder(this,AppDatabase::class.java,"database-name")
                 .allowMainThreadQueries()    //如果主线程上操作数据库,则需要添加该方法
                 .build()
          }
     }
    

至此,就完成了一个基于Room实现的数据库操作。

本地化存储

使用Room实现本地化存储可以更加方便地实现应用的开发。可以使用Room提供的TypeConverter来表示自定义类型,在对象与数据库之间进行转换。

例如,需存储以下用户信息:

data class User(
    val name: String,
    val age: Int,
    val address: Address
)

data class Address(
    val street: String,
    val city: String,
    val zipcode: String
)

则可以分别定义两个TypeConverter:

class Converters {
    @TypeConverter
    fun fromAddress(address: Address): String {
        val gson = Gson()
        return gson.toJson(address)
    }

    @TypeConverter
    fun toAddress(data: String): Address {
        val typeOf = object : TypeToken<Address>() {}.type
        return Gson().fromJson(data, typeOf)
    }
}

在Database定义中添加TypeConverters注解进行标记:

@Database(entities = arrayOf(User::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

接下来就可以使用用户信息进行数据库操作了。

结论

总的来说,Room比较适合小型的应用程序,旨在为对象它是一个好的orm库。 对于那些需要更大而复杂的数据库,更大的存储数据和更多复杂查询的应用,则是SQLite的更好的选择。 虽然没有ORM适用于一切,但Room可以,能够在许多应用程序中以简单和高效的方式进行类和数据库之间的映射。 Room从Complexity角度为开发人员的日常工作提供了巨大的简化,并提高了应用程序的可维护性。 我个人非常喜欢这个库,我鼓励每个人尝试并看看它如何在您自己的应用程序中实现。