异步编程非常重要,现在已经成为现代应用程序中的常见部分。它增加了您的应用程序可以并行执行的工作量。这允许在后台从UI线程运行繁重的任务,从而最终为应用程序用户提供流畅和更好的体验。
在科特林的协程
Kotlin团队将协程定义为“轻量级线程”。它们是实际线程可以执行的任务。协程是在1.3版中添加到Kotlin的,它基于其他语言的既定概念。 Kotlin协程引入了一种新的并发样式,可以在Android上使用它来简化异步代码。
The official documentation says that coroutines are lightweight threads. By lightweight, it means that creating coroutines doesn’t allocate new threads. Instead, they use predefined thread pools and smart scheduling for the purpose of which task to execute next and which tasks later.
协程基本上有两种类型:
- 无堆叠
- 堆积如山
Kotlin实现了无堆栈协程,这意味着协程没有自己的堆栈,因此它们不映射在本机线程上。
为什么我们需要协程?
众所周知,当今的android开发人员拥有许多异步工具。这些包括RxJava,AsyncTasks,作业,线程。那么,为什么需要学习新的东西呢?
- 在使用Rx时,需要花费大量的精力来获得足够的信息并安全地使用它。另一方面,AsyncTask和线程可以轻松引入泄漏和内存开销。即使使用了这么多缺点的这些工具,代码也可能遭受回调的困扰,这可能会引入大量额外的代码。不仅如此,代码还变得不可读,因为它具有许多回调,这些回调最终会使设备变慢或挂起,从而导致糟糕的用户体验。
- Android是一个单线程平台,默认情况下,所有内容都在主线程上运行。在Android中,几乎每个应用程序都需要执行一些非UI操作,例如(网络调用,I / O操作),因此,在不引入协程概念的情况下,要做的是程序员将该任务分配给不同的线程,每个线程执行该任务任务完成后,他们将结果返回到UI线程以更新所需的更改。尽管在android中给出了详细的过程,但该过程涉及如何使用线程的最佳实践以有效方式执行此任务,但该过程包括许多在线程之间传递结果的回调,最终在我们的应用程序和使结果恢复原状的等待时间增加了。
- 在Android上,每个应用程序都有一个主线程(该主线程处理所有UI操作,例如绘图视图和其他用户交互。如果该主线程上进行的工作过多,例如网络调用(例如,获取网页),则这些应用程序将似乎挂起或放慢速度,导致糟糕的用户体验。
Kotlin协程功能
协程是Android上异步编程的推荐解决方案。协程的一些突出特点在下面给出。
- 轻量级的:由于支持悬挂,因此可以在一个线程上运行许多协程,而这不会阻塞协程正在运行的线程。挂起可以释放内存,避免阻塞,同时支持多个并行操作。
- 内置取消支持:取消是通过正在运行的协程层次结构自动生成的。
- 内存泄漏更少:它使用结构化并发在作用域内运行操作。
- Jetpack集成:许多Jetpack库都包含提供完整协程支持的扩展。一些库还提供了自己的协程作用域,可以将其用于结构化并发。
Kotlin协程vs线程
- 从一个线程获取数据并将其传递到另一个线程需要花费大量时间。它还引入了许多回调,导致代码的可读性降低。另一方面,协程消除了回调。
- 创建和停止线程是一项昂贵的工作,因为它涉及创建自己的堆栈。而与协程相比,创建协程非常便宜。协程没有自己的堆栈。
- 线程正在阻塞,而协程是可挂起的。通过阻塞,它意味着当线程休眠一段时间后,整个线程将被阻塞,它无法执行任何其他操作,而由于协程是可挂起的,因此当它们被延迟几秒钟时,它们可以执行任何其他工作。
- 与多线程相比,协程提供了非常高的并发性,因为多线程涉及阻塞和上下文切换。与协程相比,使用线程进行上下文切换的速度较慢,因为只有在1个线程的工作结束后才能切换线程上下文,但是对于协程,它们可以随时更改上下文,因为它们是可挂起的。
- 协程轻巧,超快。协程比线程快,因为线程是由操作系统管理的,而协程是由用户管理的。具有数千个协同程序一起工作要比具有数十个线程一起工作好得多。
Kotlin协程依赖
将这些依赖项添加到build.gradle应用程序级文件中。
Kotlin
// dependencies to import in project
dependencies
{
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x.x"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:x.x.x"
}
Kotlin
// pseudo kotlin code for demonstration
// involves a series of callbacks from fetchAndShowUser
// to fetchUser and then to showUser
fun fetchAndShowUser()
{
fetchUser
{
user -> showUser(user)
}
}
Kotlin
//pseudo kotlin code for demonstration
suspend fun fetchAndShowUser()
{
// fetch on IO thread
val user = fetchUser()
// back on UI thread
showUser(user)
}
Note: x.x.x is the version of the coroutine.
Kotlin协程示例
假设我们要从数据库中获取一些用户并将其显示在屏幕上。为了从数据库中获取数据,我们必须执行网络调用,从数据库中获取用户,并将其显示在屏幕上。可以通过使用回调或协程来完成对用户的提取。
使用回调:
科特林
// pseudo kotlin code for demonstration
// involves a series of callbacks from fetchAndShowUser
// to fetchUser and then to showUser
fun fetchAndShowUser()
{
fetchUser
{
user -> showUser(user)
}
}
使用协程:
科特林
//pseudo kotlin code for demonstration
suspend fun fetchAndShowUser()
{
// fetch on IO thread
val user = fetchUser()
// back on UI thread
showUser(user)
}
正如上面讨论的,使用回调将降低代码的可读性,因此,就协同程序的可读性和性能而言,更好地使用协程。如上所述,协程除了不具有回调外,还具有许多优点,例如它们无阻塞,易于创建且创建起来不昂贵。