Kotlin中的Suspend函数:2025年它是什么以及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin中suspend关键字背后隐藏着什么?



如果你曾经用Kotlin编写过代码,并尝试调用一个带有suspend修饰符的函数,但不在协程中——你很可能遇到了编译错误。这不是bug,而是一个特性。Suspend函数是Kotlin异步编程的基础。到了2025年,它们变得更加方便,但新手(甚至是有经验的开发者)的疑问依然存在。Stack Overflow上最热门的问题之一——“Kotlin协程中的suspend函数是什么意思?”——已经获得了数千次浏览。让我们一劳永逸地弄清楚。



Suspend函数——不是魔法,而是一种契约



想象一下你点了一份披萨。你给餐厅打电话,下了订单,然后不必在电话旁等20分钟,而是继续做你自己的事情。当披萨准备好时,他们会打电话给你——你“回到”通话中。这就是suspend函数:它可以暂停自己的执行,而不阻塞线程,然后在结果可用时恢复执行。



从技术上讲,suspend并不是一个凭空让函数异步的关键字。它是一种契约:函数可以暂停,但不是必须的。Kotlin编译器会将这样的函数转换为一个状态机,能够保存和恢复其状态。



代码中的suspend函数是什么样的?



这是一个最简单的例子:



suspend fun fetchUserData(userId: String): User {    delay(1000) // 模拟网络请求    return User(userId, "Alexey")}


你不能在协程之外直接调用fetchUserData:



// 编译错误!fun main() {    val user = fetchUserData("123") // Suspend函数'fetchUserData'只能从协程或另一个suspend函数中调用}


要调用它,你需要处于协程内部。例如:



fun main() = runBlocking {    val user = fetchUserData("123")    println(user.name) // Alexey}


runBlocking是普通世界和协程世界之间的桥梁。在实际项目中,你几乎不会在生产环境中使用它(除了测试和main函数)。相反,你会通过CoroutineScope来启动协程。



“引擎盖下”发生了什么?



当编译器看到suspend时,它会生成一个额外的参数——一个Continuation对象。这个对象存储了协程被暂停的点以及所有局部变量。正因为如此,协程可以在一个线程中“休眠”,然后在另一个线程中“唤醒”——而不会阻塞。



重要提示:suspend函数不会阻塞线程。当它“休眠”时(例如,等待服务器响应),线程可以执行其他任务。这是与旧方法(Thread.sleep、回调地狱)的关键区别。



2025年使用suspend函数的最佳实践



近年来,Kotlin生态系统发展迅速。出现了新的库,编译器和IDE也得到了改进。以下是现在值得了解和应用的内容。



1. 不要创建不会暂停的suspend函数



如果一个函数不包含对其他suspend函数的调用(例如,delay、withContext、通过Ktor/Retrofit调用API),就不要给它加上suspend。这会误导人,并增加不必要的开销。



// 不好suspend fun formatName(first: String, last: String): String {    return "$first $last".trim()}

// 好fun formatName(first: String, last: String): String { return "$first $last".trim()}


2. 使用withContext切换调度器



如果你需要执行阻塞操作(读取文件、操作数据库),不要将函数标记为suspend,也不要让它

博客

书籍推荐