ROOM数据库结合其它Library的使用介绍
本文主要介绍room数据库配合其它Library的使用介绍,基本用法请查看Android Jetpack ROOM数据库用法介绍
room
数据库默认不允许在ui线程
操作数据库
比如查询数据只能先创建一个子线程操作
@Dao
abstract class UserDao {
@Query("select * from tab_user")
abstract fun getAll(): List<User>
}
class RoomActivity : AppCompatActivity() {
private var adapter: RoomAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_room)
title = "Room Example"
AppDataBase.getInstance().mockData()
initRecyclerView()
}
fun queryUser(view: View) {
loadUser()
}
private fun loadUser() {
//必须在子线程操作
Thread {
val data = AppDataBase.getInstance().userDao().getAll()
runOnUiThread {
adapter?.data = data
}
}.start()
}
...
}
当然可以调用allowMainThreadQueries()
方法改变room
数据库的默认配置,允许在ui线程
查询数据,但个人强烈不建议这么做
可以使用以下几种方式操作数据库
结合LiveData
首先添加LiveData
需要的相关依赖(一般下面的依赖会自动导入)
implementation "androidx.lifecycle:lifecycle-runtime:2.0.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
kapt "androidx.lifecycle:lifecycle-compiler:2.0.0"
然后将Dao
层抽象方法的返回值改成LiveData<T>
@Dao
abstract class UserDao {
@Query("select * from tab_user")
abstract fun getAll(): LiveData<List<User>>
}
在activity中的使用如下
class RoomActivity : AppCompatActivity() {
...
private fun loadUser() {
AppDataBase.getInstance().userDao().getAll().observe(this, Observer {
adapter!!.data = it
})
}
...
}
UserDao
的getAll()
方法返回的是一个RoomTrackingLiveData
(继承LiveData
)对象, 当你调用observe
方法的时候, 会在LiveData
的onActive()
回调中执行查询操作,会使用AppDataBase
的QueryExecutor
(默认是大小为4的线程池)对象在子线程中执行查询操作,查询完成之后,会通过LiveData
的postValue(value)
方法将结果在主线程中通知到你的Observer
回调
由于LiveData
的observe
会绑定Activity
的生命周期,所以它还有一个优势是 只会在界面可见的时候才会把数据回调给你 去刷新ui
如果你不需要绑定activity
生命周期,可调用observeForever()
方法
AppDataBase.getInstance().userDao().getAll().observeForever {
adapter!!.data = it
}
如果你关心结合MVVM
的具体用法,请参考googlesamples
的 android-architecture-components 的 BasicSample
项目
结合rxjava2
首先添加rxjava2
需要的相关依赖
implementation "androidx.room:room-rxjava2:2.1.0"
implementation "io.reactivex.rxjava2:rxjava:2.2.10"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
然后将Dao
层抽象方法的返回值改成Flowable<T>
@Dao
abstract class UserDao {
@Query("select * from tab_user")
abstract fun getAll(): Flowable<List<User>>
}
在activity中的使用如下
class RoomActivity : AppCompatActivity() {
...
AppDataBase.getInstance().userDao().getAll()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
adapter!!.data = it
}, {
Log.i("TAG", "error")
})
...
}
结合rxjava2
使用也不需要手动创建子线程去执行查询操作,只需要将返回值定义成Flowable
,当执行subscribe
方法的时候,里面会自动使用AppDataBase
的QueryExecutor
(默认是大小为4的线程池)对象在子线程中执行查询操作,然后通知给观察者,由于使用了observeOn指定了观察者的回调线程是在主线程,所以最后的回调在主线程中
如果你对rxjava
非常了解,相信结合rxjava
的各种操作符,会更加方便你处理更加复杂的业务场景
详细的结合rxjava2
的用法,请参考googlesamples
的 android-architecture-components 的 BasicRxJavaSampleKotlin
项目和BasicRxJavaSample
项目
结合guava
首先添加guava
需要的相关依赖
implementation "androidx.room:room-guava:2.1.0"
implementation "com.google.guava:guava:28.0-android"
然后将Dao
层抽象方法的返回值改成ListenableFuture<T>
@Dao
abstract class UserDao {
@Query("select * from tab_user")
abstract fun getAll(): ListenableFuture<List<User>>
}
在activity中的使用如下
class RoomActivity : AppCompatActivity() {
...
Futures.addCallback(AppDataBase.getInstance().userDao().getAll(), object: FutureCallback<List<User>> {
override fun onSuccess(result: List<User>?) {
runOnUiThread {
adapter!!.data = result!!
}
}
override fun onFailure(t: Throwable) {
}
}, MoreExecutors.directExecutor())
...
}
结合guava使用也是会使用AppDataBase
的QueryExecutor
(默认是大小为4的线程池)对象在子线程中执行查询操作,通过使用Futures
的addCallback
的静态方法添加
FutureCallback
回调 获取查询结果,但是由于没办法直接指定在主线程中执行回调,所以必须手动调用runOnUiThread
方法在主线程刷新ui