簡體   English   中英

從 RxJava2 遷移到 Kotlin 協程

[英]Migrating from RxJava2 to Kotlin Coroutines

我正在嘗試將我的代碼從 RxJava2 遷移到 Coroutines。 但我不確定如何實現這一目標。

例如,這是我將代碼插入房間數據庫的舊代碼:

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 調用它。 這要么意味着每個片段或活動中都必須有一個調度程序,或者整個調用線路都被掛起。

使用協程運行后台線程的正確方法是什么?

您可以在 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
    }
}

方法二創建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
    }
}

注意:當您的實例(例如 Activity/Fragment)被銷毀時,您可以調用: 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將在調用ViewModel onCleared()方法時自動取消。

要使用此選項,您需要將此依賴項包含在您的應用程序build.gradle文件中:

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha01"

在你的例子中,有趣的插入應該是一個掛起函數:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM