从SDK内的协程返回一个值(不阻塞主线程)

时间:2020-03-08 14:44:31

标签: kotlin kotlin-coroutines

我正在将SDK移植到Kotlin,这基本上是一些网络调用的包装。现有的Java版本使用回调将结果返回给开发人员。据我了解,协程似乎是实现此目的的一种合理方法,但是我在如何返回结果而又不阻塞主线程的问题上苦苦挣扎。

这是我的代码:

MainActivity.java

public void onClickButton(View v) {

    OiSDK oiSDK = new OiSDK(new NetworkHandler());
    List<Token> tokens = oiSDK.getTokens();    
}

OiSDK.kt

fun getTokens() = runBlocking {

        Log.d("OiSDK", "getTokens - from thread ${Thread.currentThread().name}")
        val tokens = async { fetchTokensFromServer() }.await()
        tokens        
}

suspend fun fetchTokensFromServer(): List<Token> {

    val startTime = System.currentTimeMillis()
    Log.d("OiSDK", "fetchTokensFromServer - from thread ${Thread.currentThread().name}")
    var tokens = ArrayList<Token>()

    val response = networkHandler.networkAPI.authorize(registrationUri,
            authorizationHeader, Constants.TOKEN_GRANT_TYPE_AUTHORIZATION_CODE,
            code, redirectUrl)

    tokens.add(new Token(response))

    val endTime = System.currentTimeMillis()
    Log.d("OiSDK", "Time taken: ${endTime - startTime}")

    return  tokens
}

日志跟踪:

2020-03-08 22:18:24.741 11740-11740/D/MainActivity: Update progessBar 14 - from thread main
2020-03-08 22:18:24.844 11740-11740/D/MainActivity: Update progessBar 15 - from thread main
2020-03-08 22:18:24.945 11740-11740/D/MainActivity: Update progessBar 16 - from thread main
2020-03-08 22:18:25.143 11740-11740/D/OiSDK: getTokens - from thread main
2020-03-08 22:18:25.150 11740-11818/D/OiSDK: fetchTokensFromServer - from thread main
2020-03-08 22:18:28.202 11740-11740/D/OiSDK: Time taken: 3058
2020-03-08 22:18:28.217 11740-11740/D/MainActivity: Update progessBar 17 - from thread main
2020-03-08 22:18:28.228 11740-11740/D/MainActivity: Update progessBar 18 - from thread main
2020-03-08 22:18:28.320 11740-11740/D/MainActivity: Update progessBar 19 - from thread main

问题:

  1. runBlocking阻塞主线程(如在多个地方所述,包括文档)。
  2. 使用范围(例如CoroutineScope(Dispatchers.IO).launch)将改为使用工作线程进行网络调用,但是getTokens仍会阻塞主线程。
  3. 如果我对launch使用任何范围,则不知道如何返回结果。

协程是否真的适合此用例,因为我不仅要更新某些UI,还需要返回SDK范围之外的内容?如果是这样:那怎么实现?

0 个答案:

没有答案