先决条件: Android上的Kotlin协程
众所周知,协程总是在特定的上下文中启动,并且该上下文描述了协程将在哪个线程中启动。通常,我们可以使用GlobalScope来启动协程,而无需将任何参数传递给它,没有指定协程应在其中启动的线程。由于协程可以在任何可用线程中启动,因此此方法并不能为我们提供太多控制,因此无法预测已启动协程的线程。
Kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// coroutine launched in GlobalScope
GlobalScope.launch() {
Log.i("Inside Global Scope ",Thread.currentThread().name.toString())
// getting the name of thread in
// which our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
}
}
Kotlin
GlobalScope.launch(Dispatchers.Main) {
Log.i("Inside Global Scope ",Thread.currentThread().name.toString())
// getting the name of thread in which
// our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
Kotlin
GlobalScope.launch(Dispatchers.IO) {
Log.i("Inside IO dispatcher ",Thread.currentThread().name.toString())
// getting the name of thread in which
// our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
Kotlin
GlobalScope.launch(Dispatchers.Default) {
Log.i("Inside Default dispatcher ",Thread.currentThread().name.toString())
// getting the name of thread in which
// our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
日志输出如下所示:
我们可以看到无法启动协程的线程,有时它是DefaultDispatcher-worker-1或DefaultDispatcher-worker-2或DefaultDispatcher-worker-3。
调度员如何解决上述问题?
调度程序帮助协程确定必须执行工作的线程。调度程序作为参数传递给GlobalScope ,方法是根据我们希望协程执行的工作,提及可以使用哪种类型的调度程序。
调度员类型
主要有4种类型的调度程序。
- 主调度员
- IO分派器
- 默认调度程序
- 无限制调度程序
主调度员:
它在主线程中启动协程。它通常在需要在协程中执行UI操作时使用,因为只能从主线程(也称为UI线程)更改UI。
科特林
GlobalScope.launch(Dispatchers.Main) {
Log.i("Inside Global Scope ",Thread.currentThread().name.toString())
// getting the name of thread in which
// our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
IO分派器:
它在IO线程中启动协程,用于执行所有数据操作,例如联网,从数据库读取或写入,读取或写入文件,例如:从数据库中获取数据是IO操作,它在IO线程上完成。
科特林
GlobalScope.launch(Dispatchers.IO) {
Log.i("Inside IO dispatcher ",Thread.currentThread().name.toString())
// getting the name of thread in which
// our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
默认调度程序:
它在默认线程中启动协程。当我们计划进行复杂且长时间运行的计算时,应该选择此选项,这可能会阻塞主线程并冻结UI,例如:假设我们需要进行10,000次计算,并且正在UI线程上进行所有这些计算,即main线程,如果我们等待结果或10,000个计算,那么到那个时候,我们的主线程将被阻塞,我们的UI将被冻结,从而导致糟糕的用户体验。因此,在这种情况下,我们需要使用默认线程。 Dispatchers代表在GlobalScope中启动协程时使用的默认调度程序。默认值,并且使用共享的后台线程池,因此launch(Dispatchers.Default){…}与GlobalScope.launch {…}使用相同的调度程序。
科特林
GlobalScope.launch(Dispatchers.Default) {
Log.i("Inside Default dispatcher ",Thread.currentThread().name.toString())
// getting the name of thread in which
// our coroutine has been launched
}
Log.i("Main Activity ",Thread.currentThread().name.toString())
无限制调度程序:
顾名思义,无限制调度程序不限于任何特定线程。它在当前调用框架中执行协程的初始延续,并让协程在相应的挂起函数使用的任何线程中恢复,而无需强制执行任何特定的线程策略。