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" }