Room使用簡介

Room簡介

Room是jetpack中的一個組件,它提供了ORM功能。Room用起來很是方便,而且能夠和LiveData結合,大大下降手動操做數據的複雜度。Room包含3個主要的組件:java

  • Database。表示一個數據庫。
  • Entity。定義了數據表的結構。
  • DAO。提供訪問數據庫的接口。

在使用Room時,這三個組件都會用到。android

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模式就是app

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

能夠看出來,從Entity到SQL的映射是很是直觀的。ide

Entity不單單是一個數據容器,也能夠具備行爲。下面的例子就很好的展現了這一點。ui

@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

咱們仍是從例子入手。code

@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"
}
相關文章
相關標籤/搜索