runBlocking的context参数有默认值。但是在Android Studio中查看源代码,发现源代码中定义如下:
@Throws(InterruptedException::class) public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T
这就很奇怪了。因为doc中明明注释称context参数具有默认值,而且官方文档给出的签名如下:
expect fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T
并且Kotlin在Github仓库上的源代码也确实与IDE中一致。
而且实际调试时可以发现确实传入了默认参数。那么到底是怎么回事呢?
经过了反编译、查看文档与仓库多次对照后,终于发现问题所在:
问题的关键在于expect
和actual
。初学者(比如我)可能会简单地不怎么注意函数签名的这一部分,然而正是这里造成了默认参数在源代码中令人困惑的现象!
由于expect定义处已经给出了默认参数,因此当调用到actual函数时,确实可以起到传入默认参数的作用。然而,令人十分困惑的是,在IDE中查找函数位置只能溯源到actual的函数而不是expect部分,因此很可能产生误解。
吃一堑长一智,以后再遇到类似地情况,请注意方法签名是否有actual!默认参数可能定义在expect部分中!另外,优先查看官方文档,IDE溯源代码可能产生误解。