在Kotlin中,通过指示要使用的调度程序(IO,Main等)来指定要在其上运行代码的线程类型。以类似的方式,使用rxJava,您还可以指示要在哪个线程上运行。但是,使用rxJava时,通常会在IO线程上运行某些操作来执行后台工作,然后切换到主线程(即UI线程)以显示内容。
但是我看过很多代码,其中协程仅使用主线程。它不会从IO线程切换到主线程。尽管我确定它存在,但我还没有在rxJava中看到它。
但是我的问题是你为什么要这样做?如果您只打算使用主线程,那为什么还要使用协程或rxJava呢?在主线程上运行协程与在没有协程的情况下在主线程上运行相同吗?
答案 0 :(得分:2)
我看过很多代码,其中协程仅使用主线程。
协程通常会调用在诸如Dispatchers.IO
之类的另一个线程上运行的代码,但是它通常发生在“幕后”。例如,考虑来自Android docs的以下代码:
suspend fun fetchDocs() {
val result = get("https://developer.android.com")
show(result)
}
乍一看,这个协程可能不会切换线程。但是,当您查看get()
的实现时,您会发现它确实可以切换线程:
suspend fun get(url: String) = withContext(Dispatchers.IO) { /* ... */ }
如果您深入查看所看到的代码,则几乎总会发现切换到工作线程池(例如Dispatchers.IO
)(否则,像您指出的那样使用协程毫无意义)。
但是我的问题是你为什么要这样做?
大多数协程构建器(例如viewModelScope
都默认使用Dispatchers.Main
的原因是因为这样您就不必担心“顶级代码”的线程安全性。一般模式是“在Dispathers.Main
上运行所有协程,但在必要时切换到Dispathers.IO
,以免阻塞Main
线程。”
这样,您就可以拥有简单的代码。在上面的示例中,show(result)
方法不需要是线程安全的,因为它将仅在Main
线程中使用。
只要代码不阻塞主线程,在主线程上运行代码就没有问题,这通常意味着“不执行磁盘或网络IO”。