前言
Android Jetpack是Google在18年IO大会上推荐的一整套组件库,它的出现填补了之前Android中自带的一些缺陷,例如Handler的内存泄露、Camera的不易用性、后台调度难以管理等等。所以我打算把整个架构组件系统性的学习一下,在这里和大家分享,希望能帮助到其他学习者。本系列文章包含十篇:
- Android Jetpack全家桶(一)之Jetpack介绍
 - Android Jetpack全家桶(二)之Lifecycle生命周期感知
 - Android Jetpack全家桶(三)之ViewModel控制器
 - Android Jetpack全家桶(四)之LiveData数据维持
 - Android Jetpack全家桶(五)之Room ORM库
 - Android Jetpack全家桶(六)之Paging分页库
 - Android Jetpack全家桶(七)之WorkManager工作管理
 - Android Jetpack全家桶(八)之Navigation导航
 - Android Jetpack全家桶(九)之DataBinding数据绑定
 - Android Jetpack全家桶(十)之从0到1写一个Jetpack项目
 
介绍
Room是基于SQLite实现的,一款具备比较全面的SQLite功能的ORM库。可以理解为它是对SQLite的增强优化版。
平时在日常开发中,ORM库用得比较多的是GreenDao、LitePal、Realm等优秀的开源库,但是它们都是第三方的。而如今Google自己推出了一款ORM库,也就是本篇要介绍的Room。毕竟是亲儿子,我们作为Android开发者找不到不去学习它的理由。接下来我们一起来看看吧。
(Tips:ORM是建立关系对象映射,也就是我们常用到的数据持久)
如何使用?
一,添加依赖
App.build.gradle
// room
def room_version = '2.2.0-alpha01'
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
kapt "android.arch.persistence.room:compiler:$room_version"
二,初始化DB
class App: Application() {
    companion object{
        var instance: App? = null
    }
    var db: AppDatabase? = null
    override fun onCreate() {
        super.onCreate()
        instance = this
        db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "db_book"
        ).build()
    }
}
三,建立实体类
@Entity
data class BookBean(
    @PrimaryKey var uid: Int,
    @ColumnInfo(name = "book_name") var bookName: String?,
    @ColumnInfo(name = "is_like") var isLike: Boolean?
)
四,建立Dao层
@Dao
interface BookDao {
    @Insert
    fun insertAll(books: List<BookBean>)
    @Delete
    fun delete(book: BookBean)
    @Update
    fun updateBook(book: BookBean)
    @Query("SELECT * FROM bookbean")
    fun getAll(): List<BookBean>
    @Query("SELECT * FROM bookbean WHERE is_like IN (:isLike)")
    fun getAllByLike(isLike: Boolean): List<BookBean>
}
@Database(entities = [BookBean::class], version = 1,exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
    abstract fun bookDao(): BookDao
    //...Other Dao
}
五,Dao层业务实现
// Room added data
val bookStore = arrayOf("...")
val books: MutableList<BookBean> = mutableListOf()
for ((index, bookName) in bookStore.withIndex()){
    val book = BookBean(index,bookName,false)
    books.add(book)
}
App.instance?.db?.bookDao()?.insertAll(books)
doAsync {
    // Room delete data
    val delResult = App.instance?.db?.bookDao()?.delete(datas[position])
    if(null != delResult){
        uiThread {
            datas -= datas[position]
            notifyDataSetChanged()
        }
    }
}
doAsync {
    // Room update data
    datas[position].isLike = !datas[position].isLike!!
    App.instance?.db?.bookDao()?.updateBook(datas[position])
    uiThread {
        notifyDataSetChanged()
    }
}
doAsync {
    // Query data for Room
    mDatas = App.instance?.db?.bookDao()?.getAll()!!
    if(mDatas.isEmpty()){
        initData()
    }
    uiThread {
        mBookAdapter = BookAdapter(this@BookActivity,mDatas)
        mRecyclerView.adapter = mBookAdapter
        mBookAdapter.notifyDataSetChanged()
    }
}
doAsync {
    // Query like data for Room
    mDatas = App.instance?.db?.bookDao()?.getAllByLike(true)!!
    uiThread {
        if(mDatas.isNotEmpty()){
            for(bookBean:BookBean in mDatas){
                mStringBuilder.append(bookBean.bookName)
                mStringBuilder.append(",")
            }
            mTvLike.text = "喜欢的书:$mStringBuilder"
        }else{
            mTvLike.text = "喜欢的书:暂无(请在主页添加)"
        }
    }
}
分析Room
如图所示:

Room有3个主要部分:
数据库:包含数据库持有者,并作为应用程序持久关系数据的基础连接的主要访问点。
使用@Database注释的类应满足以下条件: 1,是一个扩展RoomDatabase的抽象类。 2,在注释中包括与数据库关联的实体列表。 3,包含一个具有0个参数的抽象方法,并返回使用@Dao注释的类。
在运行时,您可以通过调用Room.databaseBuilder()或Room.inMemoryDatabaseBuilder()来获取Database实例。
实体:表示数据库中的表。
DAO:包含用于访问数据库的方法。
该应用程序使用Room数据库来获取与该数据库关联的数据访问对象或DAO。 然后,应用程序使用每个DAO从数据库中获取实体,并将对这些实体的任何更改保存回数据库。 最后,应用程序使用实体来获取和设置与数据库中的表列对应的值。
注意事项
实现查询和修改操作时,需要在异步调用Room,如果不在异步调用则会报出以下异常:
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long periods of time.
了解更多
有关于数据库升级和数据库文件导出,可以查阅这篇文章
结语
最后,希望大家可以结合demo进行拓展性的学习。