从RxJava2迁移到Kotlin协程

时间:2019-07-19 12:21:26

标签: android kotlin

我正在尝试将我的代码从RxJava2迁移到协程。但是我不确定如何实现。

例如,这是我的旧代码,用于将代码插入“会议室数据库”:

fun insert(note: Note) = Single.fromCallable {
        dao.insert(note)
    }.subscribeIn({ id ->
        note.id = id
        if (note.bitmap != null) update(note)
    }

注意:此代码位于名为DataHelper的对象中,该对象包含所有方法和Dao对象。

这是道电话:

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(note: Note): Long

由于我无法从主线程调用暂停函数,因此尚不清楚尝试用协程调用替换该代码。

fun insert(note: Note) {
        val id = withContext(Dispatchers.IO) {
            dao.insert(note)
        }
        note.id = id
        if (note.bitmap != null) update(note)
    }

dao.insert()现在是Dao中的暂停函数。

使insert(Note)函数成为暂停函数意味着我必须从任何地方(例如,片段)使用Dispatcher对其进行调用。这要么意味着每个片段或活动中都必须有一个Dispatcher,要么必须暂停整个呼叫。

使用协程运行后台线程的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

在您的示例中,有趣的插入应该是一个暂停函数:

suspend fun insert(note: Note) {
        withContext(Dispatchers.IO) {
            dao.insert(note)
        }
        //note.id = id
        //if (note.bitmap != null) update(note)
    }

,然后在ViewModel中使用viewModelScope:

viewModelScope.launch {
            noteRepository.createNote(note)
        }

答案 1 :(得分:2)

您可以在Room Dao中使用暂停的功能:

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(note: Note): Long

每当您要访问/调用此Dao方法时,都需要CoroutineScope来完成。

方法1 使用 GlobalScope:

GlobalScope.launch(Dispatchers.IO) {
    dao.insert(note)
    withContext(Dispatchers.Main){
     // main thread calls here, e.g. updating view, showing toast, etc
    }
}

方法2 创建一个CoroutineScope

val job = SupervisorJob()
val scope = CoroutineScope(Dispatchers.IO + job)

scope.launch {
    dao.insert(note)
    withContext(Dispatchers.Main){
     // main thread calls here, e.g. updating view, showing toast, etc
    }
}
  

注意:当您的实例(例如活动/片段)被破坏时,您   可以致电:job.cancel()取消协程作业。

方法3:您可以使用CoroutineScope扩展类:

class MainActivity : AppCompatActivity(), CoroutineScope {
    override val coroutineContext: CoroutineContext = Dispatchers.IO + SupervisorJob()

    ....

    fun onSomeAction() {
        launch {
            dao.insert(note)
            withContext(Dispatchers.Main) {
                // main thread actions
            }
        }
    }
}

如果您使用ViewModel调用dao方法,则可以使用viewModelScope扩展名:

viewModelScope.launch(Dispatchers.IO) {
    dao.insert(note)
    withContext(Dispatchers.Main){
     // main thread calls here, e.g. updating view, showing toast, etc
    }
}

与其他选项不同,调用viewModelScope的{​​{1}}方法时,onCleared()将被自动取消。

要使用此选项,您需要在您的 app ViewModel文件中包括此依赖项:

build.gradle