首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kotlin-coroutines观察db变化的房间

Kotlin-coroutines观察db变化的房间
EN

Stack Overflow用户
提问于 2019-01-31 06:46:28
回答 3查看 12.2K关注 0票数 21

所以,我最近开始了协同实验,我从Rxjava2切换到协同,我还没有掌握它,但我仍然遇到了一个条件,我需要观察我的数据库的变化,并更新UI与之相对应。

RxJava曾经为我提供可流动的、可完成的等等,使用它我可以观察Db中的变化。

代码语言:javascript
复制
    abstract fun insert(data: SomeData): Long

    @Query("SELECT * FROM somedata_table")
    abstract fun getData(): Flowable<List<SomeData>>

所以,现在我经常订阅getData,并且总是观察变化。

现在输入coroutines,我使用一个带有延迟结果的挂起函数来返回我的响应。

代码语言:javascript
复制
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    abstract fun insert(data: SomeData): Long

    @Query("SELECT * FROM somedata_table")
    abstract fun getData(): List<SomeData>
代码语言:javascript
复制
suspend fun getAllSomeData():Deferred<List<SomeData>>{
        return GlobalScope.async (context= coroutineContext){
            database.myDao().getData()
        }
    }

现在我没有办法收听更新,频道在协同可能是正确的答案吗?但是我不知道如何在房间里使用它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-10-22 22:19:34

使用房间2.2.0流kotlin协同服务。这是有争议的,但我不喜欢LiveData,因为它在UI线程上给出了结果。如果您必须执行任何数据解析,则必须将所有内容推回另一个IO线程。它也比直接使用通道更干净,因为您必须执行额外的{ ..}每次您想要侦听事件时,都会调用。

Flow方法需要以下版本:

//此版本在非实验版本中使用协同和流。

代码语言:javascript
复制
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2
androidx.room:room-runtime:2.2.0
androidx.room:room-compiler:2.2.0

Dao:

代码语言:javascript
复制
@Dao
interface MyDao {
     @Query("SELECT * FROM somedata_table")
     fun getData(): Flow<List<SomeData>>
}

上课做观察:

代码语言:javascript
复制
launch {
   dao.getData().collect { data ->
    //handle data here
   }
}

如果您的调用类本身不是一个CoroutineScope,那么您就必须用它本身的上下文调用启动。可以是、GlobalScope、或您创建的其他类。在这里,我使用lifecycleScope,假设我们在一个活动类中。

代码语言:javascript
复制
lifecycleScope.launch {
   dao.getData().collect { data ->
    //handle data here
   }
}

collect lambda将接收到表中的每个udpate,就像Rx onNext调用一样。

票数 11
EN

Stack Overflow用户

发布于 2019-08-15 11:10:27

目前,有两种不同的方法。第一个是使用liveData构建器函数。要使此工作正常,需要将生命周期更新为androidx.lifecycle:*:2.2.0-alpha01或任何较新的版本。LiveData构建器函数将用于异步调用getData(),然后使用emit()发出结果。使用此方法,您将将Room getData()函数修改为挂起函数,并将返回类型包装为LiveData,替换以前使用的可流动类型。

代码语言:javascript
复制
@Query("SELECT * FROM somedata_table")
abstract suspend fun getData(): LiveData<List<SomeData>>

在您的视图模型中,您创建了一个引用您的房间数据库的liveData

代码语言:javascript
复制
val someData: LiveData<SomeData> = liveData {
    val data = database.myDao().getData() 
    emit(data)
}

第二种方法是以流的形式从DB中获取数据。若要使用此功能,您需要将“空间”更新为androidx.room:room-*:2.2.0-alpha02 (当前最新版本)或更新版本。此更新使@Query方法成为返回类型流,如果查询中的观察表无效,返回的流将重新发出一组新的值。用通道返回类型声明DAO函数是一个错误

代码语言:javascript
复制
@Query("SELECT * FROM somedata_table")
abstract fun getData(): Flow<List<SomeData>?>

返回类型是可空列表的流。该列表为空,因为当查询没有获取数据时,Room将返回null。

为了从流中获取数据,我们将在演示者/视图模型中使用终端操作符collect{ }。最好在ViewModel中这样做,因为它附带了一个ViewModelScope。下面给出的解决方案假设我们是在ViewModel中这样做的,在这里我们提供了一个viewModelScope。

代码语言:javascript
复制
    fun loadData(){
        viewModelScope.launch {
            database.myDao()
               .getData()
               .distinctUntilChanged().
               .collect{
                        it?.let{ /** Update your obsevable data here **/
               }
    }
票数 7
EN

Stack Overflow用户

发布于 2019-02-05 12:04:15

级依赖关系:

代码语言:javascript
复制
dependencies {
    compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-reactive', version: '1.1.1'
}

房Dao

代码语言:javascript
复制
@Dao
interface HistoryDao : BaseDao<HistoryEntity> {

    @Query("select * from History order by time desc")
    fun observe(): Flowable<List<HistoryEntity>>

    ...
}

(下面是(browserHistoryInteractor )(数据和片段/演示器之间的一层)

代码语言:javascript
复制
// To get channel of List<HistoryEntity>:
import kotlinx.coroutines.reactive.openSubscription

fun observe() = historyDao.observe().openSubscription() // convert list to Coroutines channel

Presenter/Fragment/Activity (端点(在我的例子中,它是生命周期感知的演示者))

代码语言:javascript
复制
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch

private val compositeJob = Job() // somewhat equivalent "compositeDisposable" in rx

override fun onCreate() {
    super.onCreate()

    launch(compositeJob) { // start coroutine
        val channel = browserHistoryInteractor.observe() 
        for (items in channel) {  // waits for next list of items (suspended)
            showInView { view?.setItems(items) }
        }
    }
}

override fun onDestroy() {
    compositeJob.cancel() // as in rx you need to cancel all jobs
    super.onDestroy()
}

01SNEhG5Qs&index=5 29:25

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54454829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档