美文网首页
Room使用简介

Room使用简介

作者: tommwq | 来源:发表于2019-11-15 20:01 被阅读0次

    Room简介

    Room是jetpack中的一个组件,它提供了ORM功能。Room用起来非常方便,并且可以和LiveData结合,大大降低手动操作数据的复杂度。Room包含3个主要的组件:

    • Database。表示一个数据库。
    • Entity。定义了数据表的结构。
    • DAO。提供访问数据库的接口。

    在使用Room时,这三个组件都会用到。

    Entity

    Entity用于定义数据表的结构。我们首先看一个简单的例子。

    @Entity(tableName="users")
    data class User (
        @PrimaryKey var uid: Int,
        @ColumnInfo(name = "first_name") var firstName: String?,
        @ColumnInfo(name = "last_name") var lastName: String?
        @Ignore var picture: Bitmap?
    )
    

    这里使用了很多注解。@Entity表示类是一个Entity对象,tableName参数是Entity的表名。@PrimaryKey表示域是一个主键。Room要求主键必须是Int或Long型。@ColumnInfo声明了列名和域名的对照关系。如果列名和域名相同,可以省略这个注解。@Ignore表示这个域在数据表中没有对应的列。因此上面这个Entity对应的SQL模式就是

    CREATE TABLE users (
        INT uid PRIMARY KEY,
        TEXT first_name,
        TEXT last_name
    );
    

    可以看出来,从Entity到SQL的映射是非常直观的。

    Entity不仅仅是一个数据容器,也可以具有行为。下面的例子就很好的展示了这一点。

    @Entity(tableName = "plants")
    data class Plant(
        @PrimaryKey @ColumnInfo(name = "id") val plantId: String,
        val name: String,
        val description: String,
        val growZoneNumber: Int,
        val wateringInterval: Int = 7,
        val imageUrl: String = ""
    ) {
        fun shouldBeWatered(since: Calendar, lastWateringDate: Calendar) =
            since > lastWateringDate.apply { add(DAY_OF_YEAR, wateringInterval) }
    
        override fun toString() = name
    }
    

    在这个例子里的Entity拥有行为,并且字段也可以设置默认值。

    Entity告诉Room如何进行Java对象和SQL记录之间的转换。要访问数据表,我们还需要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这几个注解将Java方法和SQL查询语句关联起来。这里的Dao是一个接口,我们不需要手动编写接口的实现类,Room会自动生成它。

    如果数据量较大,查询可能会占用很多时间。为了避免ANR,我们通常需要将数据库查询放到后台进行里执行。如何将查询到的数据传递给主线程呢?Room通过LiveData实现这一点。这也是Room最好用的地方。

    @Dao
    interface PlantDao {
        @Query("SELECT * FROM plants ORDER BY name")
        fun getPlants(): LiveData<List<Plant>>
    
        @Query("SELECT * FROM plants WHERE growZoneNumber = :growZoneNumber ORDER BY name")
        fun getPlantsWithGrowZoneNumber(growZoneNumber: Int): LiveData<List<Plant>>
    
        @Query("SELECT * FROM plants WHERE id = :plantId")
        fun getPlant(plantId: String): LiveData<Plant>
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        fun insertAll(plants: List<Plant>)
    }
    

    Database

    我们已经知道Room会生成Dao的实现类。要如何得到这个类呢?答案是通过Room.databaseBuilder得到Database,在用Database得到Dao。

    @Database(entities = [User::class], version = 1)
    abstract class AppDatabase: RoomDatabase() {
        abstract fun userDao(): UserDao
    }
    
    val db = Room.databaseBuilder(
        applicationContext,
        AppDatabase::class.java,
        "database-name"
    ).build()
    

    Room会自动生成类,这个动作是在编译期完成的,因为我们需要引入编译插件。

    apply plugin: 'kotlin-kapt'
    
    dependencies {
        def room_version = "2.1.0-alpha04"
        implementation "androidx.room:room-runtime:$room_version"
        kapt "android.arch.persistence.room:compiler:1.0.0"
    }
    

    相关文章

      网友评论

          本文标题:Room使用简介

          本文链接:https://www.haomeiwen.com/subject/mmasictx.html