从 RxJava2 迁移到 Kotlin 协程
Migrating from RxJava2 to Kotlin Coroutines
我正在尝试将我的代码从 RxJava2 迁移到协程。但我不确定如何实现。
例如,这是我将代码插入房间数据库的旧代码:
fun insert(note: Note) = Single.fromCallable {
dao.insert(note)
}.subscribeIn({ id ->
note.id = id
if (note.bitmap != null) update(note)
}
注意:这段代码在一个名为 DataHelper 的对象中,该对象包含所有方法和 Dao 对象。
这是 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,要么 activity,或者暂停整个调用行。
使用协程 运行 后台线程的正确方法是什么?
在你的例子中,fun insert 应该是一个挂起函数:
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)
}
您可以在您的 Room Dao 中使用暂停功能:
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(note: Note): Long
无论什么时候你想access/call这个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
}
}
Note: When your instance (e.g. Activity/Fragment) is destroyed, you
can call: job.cancel()
to cancel your coroutine jobs.
方法 3:您可以使用 CoroutineScope
:
扩展您的 class
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()
方法时自动取消。
要使用此选项,您需要在 app 级别 build.gradle
文件中包含此依赖项:
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha01"
我正在尝试将我的代码从 RxJava2 迁移到协程。但我不确定如何实现。
例如,这是我将代码插入房间数据库的旧代码:
fun insert(note: Note) = Single.fromCallable {
dao.insert(note)
}.subscribeIn({ id ->
note.id = id
if (note.bitmap != null) update(note)
}
注意:这段代码在一个名为 DataHelper 的对象中,该对象包含所有方法和 Dao 对象。
这是 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,要么 activity,或者暂停整个调用行。
使用协程 运行 后台线程的正确方法是什么?
在你的例子中,fun insert 应该是一个挂起函数:
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)
}
您可以在您的 Room Dao 中使用暂停功能:
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(note: Note): Long
无论什么时候你想access/call这个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
}
}
Note: When your instance (e.g. Activity/Fragment) is destroyed, you can call:
job.cancel()
to cancel your coroutine jobs.
方法 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()
方法时自动取消。
要使用此选项,您需要在 app 级别 build.gradle
文件中包含此依赖项:
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha01"