Room是jetpack中的一個組件,它提供了ORM功能。Room用起來很是方便,而且能夠和LiveData結合,大大下降手動操做數據的複雜度。Room包含3個主要的組件:java
在使用Room時,這三個組件都會用到。android
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。線程
咱們仍是從例子入手。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>) }
咱們已經知道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" }