Kotlin协程学习随笔-打印协程名称

933 阅读2分钟

Kotlin协程学习中使用协程相关日志是学习协程的重要手段,例如打印协程名。默认情况下协程相关的日志是关闭的,那如何打开相关日志呢?这里主要分两种,单元测试中的日志以及Android工程中的日志,下面将分别进行讲解。此外,对于使用基础设施(startCoroutinecreateCoroutine)创建的协程,使用上述两种方法无法进行日志调试,本文将介绍一种其他的便捷方法打印日志。

1. 单元测试协程debug模式

在单元测试中设置协程debug模式,可以使用Thread.currentThread().name将当前线程和协程打印出来。那如何开启debug模式呢?这需要在configurations中将VM options设置-Dkotlinx.coroutines.debug=on,或者-ea。示意图如下所示。先打开Android Studio中相应单元测试的Configurations。点击图1的Edit Configuration,进入图2.

图片1.png

图 1

然后在图2中将VM options设置为-Dkotlinx.coroutines.debug=on,或者-ea。如图2.

图片2.png

图 2

以下是测试代码。

class ExampleUnitTest {
    @Test
    fun logTest() {
        name()
    }

    fun name() = runBlocking {
        async {
            log("1")
        }

        async {
            log("2")
        }
    }

    fun log(msg: String) = println("[${Thread.currentThread().name}$msg")\
}

debug模式关闭时,打印日志为:

[main] 1
[main] 2

debug模式开启时,日志为:

[main @coroutine#2] 1
[main @coroutine#2] 2

2. Android工程协程debug模式

Android工程中打开协程debug模式,无法直接在工程中进行设置,而是需要在Android代码中设置相应属性。设置代码如下:

System.setProperty("kotlinx.coroutines.debug""on" )

一种常用的方式是在Application初始化的时候进行设置。代码如下:

public class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        System.setProperty("kotlinx.coroutines.debug""on" )
    }
}

3.基础协程日志

对于使用createCoroutinestartCoroutine函数创建的协程,本文统一称为基础协程。对于这种类型的协程,即使打开了协程的debug模式,在Thread.currentThread().name中也不会打印协程名,因此不方便进行调试。此处可以使用另一种方式打印协程名。

我们知道我们可以通过CoroutineContext设置协程名,并且在协程中,通过coroutineContext[CoroutineName]可以打印协程的名字。既然如此,对于每个要调试的协程,我们可以先设置其名字,然后在日志打印处将其名字打印出来,就可以达到增加协程调试日志的效果了。

测试代码如下所示。

class LogTest {

    @Test
    fun logTest() {
        suspend  {
            println ("Thread name: ${Thread.currentThread().name}; Coroutine Name: ${coroutineContext[CoroutineName]}")
        }.startCoroutine(object : Continuation<Unit> {
            override val context = EmptyCoroutineContext + CoroutineName("CustomCoroutine")

            override fun resumeWith(result: Result<Unit>) {
                result.getOrThrow()
            }
        })
    }
}

以上代码打印结果如下:

Thread name: Test worker; Coroutine Name: CoroutineName(CustomCoroutine)

可见即使开启了协程debug模式,Thread.currentThread().name还是未打印协程名。但是我们可以通过coroutineContext[CoroutineName]将协程名手动打印出来。