暂停一个kotlin Coroutine不能用齐射

时间:2018-02-21 22:52:58

标签: android kotlin android-volley kotlin-coroutines

我写了以下(测试)功能,通过排球和协同程序与谷歌地图api交谈。可悲的是,当使用suspendCoroutine调用它时,它永远不会完成。如果我使用相同的功能,删除协同程序的东西并实现“正常”回调,一切正常。我有点不知道这里的问题是什么。有人能帮忙吗?

代码执行到Log.d(LOGTAG,“AFTERAFTER”),但从未到达Log.d(“findNaturalLocations”,“Response:”+ response)

suspend fun testNaturalLocations(tag: Tag, lastKnownUserLocation: 
Location): ArrayList<CLDistanceRequest> = suspendCoroutine { 
continuation ->

    Log.d("findNaturalLocations", "getDistanceAndTimeBetweenLocations")

    var distanceRequests = ArrayList<CLDistanceRequest>()

    val mapsBaseUrl = "https://maps.googleapis.com/maps/api/place/nearbysearch/"
    val mapsOutputFormat = "json"

    val location = "location=" + lastKnownUserLocation.latitude.toString() + "," + lastKnownUserLocation.longitude.toString()
    val radius = "radius=5000"
    val keyword = "keyword=Supermarket"
    val name = "name=Supermarket"
    val sensor = "sensor=true"
    val apiKey = "key=API_KEY"

    val finishedUrl = mapsBaseUrl + mapsOutputFormat + "?" + location + "&" + radius + "&" + keyword + "&" + name + "&" + sensor + "&" + apiKey

    Log.d(LOGTAG, finishedUrl)

    val jsObjectRequest = JsonObjectRequest(Request.Method.GET, finishedUrl, null,
            Response.Listener<JSONObject> { response ->
                Log.d("findNaturalLocations", "Response: " + response)

                var results = response.getJSONArray("results")

                // parse distanceRequests, ommitted for brevity

                continuation.resume(distanceRequests)
            },
            Response.ErrorListener { error ->
                Log.e("Error", error.localizedMessage, error)

                continuation.resumeWithException(error)
            }
    )

    Log.d(LOGTAG, "AFTER");

    jsObjectRequest.setShouldCache(false)
    CLGlobal.getRequestQueue().add(jsObjectRequest)

    Log.d(LOGTAG, "AFTERAFTER");
}

使用简单的回调执行相同操作可以完美无缺。

var i = 0;
    runBlocking {
        val query = async(CommonPool) {
            i = this@CLTaskList.test2()
        }

        query.await()
    }

suspend fun test2():Int = suspendCoroutine<Int> { continuation ->
    Log.d("TESTTEST", "TEST2 CALLED")
    test {
        Log.d("TESTTEST", "CONTINUATION")
        continuation.resume(it)
    }
}

fun test(completionHandler: (Int) -> Unit) {
    Log.d("TESTTEST", "TEST CALLED")
    completionHandler(1)
}

1 个答案:

答案 0 :(得分:1)

正如您在评论中所揭示的,这就是您运行查询的方式:

val query = async(CommonPool) { 
    this@CLTaskList.testNaturalLocations(tags[0], 
         CLGlobal.getInstance().mLastKnownLocation!!) 
} 
runBlocking<Unit> { query.await() }

你接近正确,但这段代码都是倒退的:

  1. 你让暂停功能在一个线程池中运行,减轻一些工作线程的阻塞义务,直到你得到你的答案(如果它被阻止,它就不在乎了);
  2. 使用runBlocking阻止GUI线程。
  3. 在正确的解决方案中,您不需要asyncCommonPoolrunBlocking,您只需要这样:

    launch(UI) {
        val result = testNaturalLocations(tags[0], 
           CLGlobal.getInstance().mLastKnownLocation!!)
        // deal with the result right here
    }
    

    由于testNaturalLocations是可暂停的功能,因此它不会阻止您的UI线程,并且当您编写的回调恢复它时,您的代码只会转到下一行,result分配