Android/Windows平台Kotlin协程表现不一致问题求助
Kotlin协程跨平台(Android/Windows)执行差异问题解决
问题背景
使用Kotlin开发Android/Windows远程控制应用(客户端+服务端),相同代码在Android平台运行正常,但在Windows平台无预期执行效果。熟悉Android协程基础,但对桌面平台协程处理逻辑不了解。
核心代码
Main.kt
fun main(): Unit = runBlocking { CoroutineScope(Job()).launch { println("connecting server") Servidor.ligar() } CoroutineScope(Job()).launch { println("connecting client") Cliente.ligar() } }
Server.kt
object Servidor { suspend fun ligar() = withContext(Dispatchers.IO) { val porta = 1777 var mensagem: String val server = ServerSocket(porta) println("Trying to connect through $porta...") val client = server.accept() val mPrintWriter = PrintWriter(client.getOutputStream(), true) val br = BufferedReader(InputStreamReader(client.getInputStream())) println("Connected by port: $porta") while (br.readLine().also { mensagem = it } != null) { println("The message: $mensagem") if (mensagem == "bye") { mPrintWriter.println("bye") break } else { mensagem = "Server returns $mensagem" mPrintWriter.println(mensagem) } } mPrintWriter.close() br.close() client.close() } }
Cliente.kt
object Cliente { suspend fun ligar() = withContext(Dispatchers.IO) { val portNumber = 1777 var str = "initialize" val mSocket = Socket(InetAddress.getLocalHost(), portNumber) val br = BufferedReader(InputStreamReader(mSocket.getInputStream())) val pw = PrintWriter(mSocket.getOutputStream(), true) pw.println(str) println(str) while (br.readLine().also { str = it } != null) { println(str) pw.println("bye") if (str == "bye") break } br.close() pw.close() mSocket.close() } }
执行结果对比
- Android平台(Logcat输出):
connecting server connecting client Trying to connect through 1777... initialize Connected by port: 1777 The message: initialize Server returns initialize The message: bye bye
- Windows平台(IntelliJ IDEA输出):
connecting server connecting client Process finished with exit code 0
问题原因
在Windows平台的runBlocking作用域中,通过CoroutineScope(Job())创建的协程作用域与runBlocking的根Job无父子关联。runBlocking仅会等待自身作用域内的代码执行完毕,当两个launch调用完成后,程序直接退出,导致后续的Socket连接、数据交互逻辑还未执行就被终止。
而Android平台通常使用与组件生命周期绑定的协程作用域(如lifecycleScope),这类作用域会自动管理协程生命周期,等待协程执行完成,因此代码能正常运行。
解决方案
方案1:直接在runBlocking作用域内启动协程
移除独立的CoroutineScope(Job()),直接使用runBlocking的作用域启动协程,此时协程会成为runBlocking的子协程,runBlocking会等待所有子协程执行完毕后再退出:
fun main(): Unit = runBlocking { launch { println("connecting server") Servidor.ligar() } launch { println("connecting client") Cliente.ligar() } }
方案2:关联协程Job并手动等待
如果需要保留独立的CoroutineScope,可将其Job与runBlocking的上下文绑定,或保存launch返回的Job实例并手动调用join()等待完成:
fun main(): Unit = runBlocking { val serverJob = CoroutineScope(coroutineContext).launch { println("connecting server") Servidor.ligar() } val clientJob = CoroutineScope(coroutineContext).launch { println("connecting client") Cliente.ligar() } // 等待两个协程全部执行完成 serverJob.join() clientJob.join() }
额外优化:调整依赖
桌面平台无需依赖kotlinx-coroutines-android(该依赖为Android平台专用),建议移除该依赖,仅保留核心协程库即可:
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4
内容的提问来源于stack exchange,提问作者Gilian Marques
相关产品推荐
相关产品推荐

